上一篇介紹了zookeeper的單機啓動,集羣模式下啓動和單機啓動有類似的地方,可是也有各自的特色。集羣模式的配置方式和單機模式也是不同的,這一篇主要包含如下內容:java
概念介紹:角色,服務器狀態算法
服務器組件啓動apache
leader選舉服務器
集羣模式會有多臺server,每臺server根據不一樣的角色會有不一樣的狀態,server狀態的定義以下網絡
public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING; }
LOOKING:表示服務器處於選舉狀態,說明集羣正在進行投票選舉,選出leader數據結構
FOLLOWING:表示服務器處於following狀態,表示當前server的角色是followeroop
LEADING:表示服務器處於leading狀態,當前server角色是leader性能
OBSERVING:表示服務器處於OBSERVING狀態,當前server角色是OBSERVERflex
對應server的角色有:線程
投票選出的leader,能夠處理讀寫請求。處理寫請求的時候收集各個參與投票者的選票,來決出投票結果
做用:
爲了支持zk集羣可擴展性,若是直接增長follower的數量,會致使投票的性能降低。也就是防止參與投票的server太多,致使leader選舉收斂速度較慢,選舉所需時間過長。
observer和follower相似,可是不參與選舉和投票,
這樣在支持集羣可擴展性的同時又不會影響投票的性能
集羣模式下服務器啓動的組件一部分和單機模式下相似,只是啓動的流程和時機有所差異
也是會啓動上面三個組件,可是由於集羣模式還有其餘組件須要啓動,因此具體啓動的邏輯不太同樣。
除了上面這些組件外,集羣模式下還有一些用來支撐集羣模式的組件
解除出來的QuorumPeerConfig配置都設置到QuorumPeer對應的屬性中,主線程啓動完QuorumPeer後,調用該線程的join方法等待該線程退出。
負責各個server之間的通訊,維護了和各個server之間的鏈接,下面的線程負責與其餘server創建鏈接
org.apache.zookeeper.server.quorum.QuorumCnxManager.Listener
還維護了與其餘每一個server鏈接對應的發送隊列,SendWorker線程負責發送packet給其餘server
final ConcurrentHashMap<Long, ArrayBlockingQueue<ByteBuffer>> queueSendMap;
這個map的key是創建網絡鏈接的server的myid,value是對應的發送隊列。
還有接收隊列,RecvWorker是用來接收其餘server發來的Message的線程,將收到的Message放入隊列中
org.apache.zookeeper.server.quorum.QuorumCnxManager#recvQueue
選舉入口在下面的方法中
org.apache.zookeeper.server.quorum.FastLeaderElection#lookForLeader
上面這個是其中的一種選舉算法,選舉過程當中,各個server收到投票後須要進行投票結果抉擇,判斷投票結果的策略有兩種
// 按照分組權重 org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical // 簡單按照是不是大多數,超過參與投票數的一半 org.apache.zookeeper.server.quorum.flexible.QuorumMaj
zookeeper中選舉使用的端口和正常處理client請求的端口是不同的,並且因爲投票的數據和處理請求的數據不同,數據傳輸的方法也不同。選舉使用的網絡傳輸相關的類和數據結構以下
各自初始化選票
發送本身的選票給其餘參選者
接收其餘參選者的選票
收到其餘參選者的選票後會放入recvqueue,這個是阻塞隊列,從裏面超時獲取
若是超時沒有獲取到選票vote則採用退避算法,下次使用更長的超時時間
校驗選票的有效性,而且當前機器處於looking狀態,開始判斷是否接受
若是收到的選票的electionEpoch大於當前機器選票的logicalclock
進行選票pk,收到的選票和本機初始選票pk,若是收到的選票勝出則更新本地的選票爲收到的選票
pk的算法
若是本機初始選票勝出則更新爲當前機器的選票
更新完選票以後從新發出本身的選票
若是n.electionEpoch == logicalclock.get()而且收到的選票pk(pk算法totalOrderPredicate)以後勝出
執行到這裏,說明收到的這個選票有效,將選票記錄下來,recvset
統計選票
判斷投票結果
org.apache.zookeeper.server.quorum.SyncedLearnerTracker#hasAllQuorums
根據具體的策略判斷
QuorumHierarchical
QuorumMaj,默認是這個
若是本輪選舉成功
選舉的整個流程爲
集羣啓動過程其實就是在單機啓動的部分基礎上,增長了關於集羣的一些組件,並且有leader的選舉。