Zookeeper集羣啓動過程算法
預啓動
數據庫
統一由QuorumPeerMain做爲啓動類服務器
讀取zoo.cfg配置文件ide
建立並啓動歷史文件清理器DatadirCleanupManager學習
判斷當前是集羣模式仍是單機模式spa
初始化線程
建立ServerCnxnFactory,orm
初始化ServerCnxnFactory,初始化一個線程,做爲整個ServerCnxnFactory的主線程而後在初始化NIO服務器server
建立Zookeeper數據管理器FileTxnSnapLog,對象
建立QuorumPeer實例,Quorum是集羣模式下特有的對象,是Zookeeper服務器實例的託管者,從集羣層面來看QuorumPeer表明了Zookeeper集羣中一臺服務器,在運行期間它會不斷檢查當前服務器實例運行的狀態。而後根據狀況進行Leader選舉。
建立內存數據庫ZKDatabase
初始化QuorumPeer,這裏把一些核心組件註冊到QuorumPeer,這些核心組件包括FileTxnSnapLog、ServerCnxnFactory和ZKDatabase,同時Zookeeper還會對QuorumPeer配置一些參數,包括服務器地址列表,選舉算法和會話超時時間等。
恢復本地數據庫
啓動ServerCnxnFactory主線程
Leader選舉
交互和數據同步(看紅色部分)
建立會話管理器
初始化Zookeeper的請求處理鏈
註冊JMX
在Leader選舉完成以後會有一個Leader和其餘服務器(Follower和Observer 統稱Learner學習者)進行交互,大體流程以下:
Leader服務器啓動Follower接收器,LearnerCnxAcceptor,來接收全部非Leader服務器的鏈接
Leader與每個Learner之間都會有一個LearnerHandler實例對應負載它們之間的消息通訊和數據同步
Learner和Leader創建鏈接後,Learner向Leader註冊,就是發送本身的信息給Leader,包括當前服務器的SID和ZXID
Leader解析Learner發來的註冊信息,在過半向Leader註冊的服務器中找到最大的epoch,而後加1,用於肯定當前集羣的epoch
Leader發送LEADERINFO給Learner
Learner收到LEADERINFO,解析出epoch和ZXID而後給Leader一個反饋
Leader收到Learner響應以後就開始與其進行數據同步
啓動Leader和Learner服務器,有過半數完成數據同步就能夠啓動了。
Leader選舉
選舉原則就是比計較MYID、ZXID,這裏咱們以3臺爲例,其實2臺也能夠完成選舉,可是一般集羣規模最小是3臺
服務器啓動期間的選舉
Server1 myid:1 zxid:0
Server2 myid:2 zxid:0
Server3 myid:3 zxid:0
每一個服務器都會發出一條投票且都是投給本身,以Server1爲例(1,0),把這個信息發送到集羣中其餘服務器上。固然它本身也會收到別人的投票信息
每一個服務器收到其餘服務器的投票,先會檢查有效性包括檢查是不是本輪投票以及是否來自LOOKING狀態的服務器發出的
處理投票,首先比較ZXID,值最大的爲Leader,若是值同樣那麼就比較myid,myid最大的爲Leader,Server1會收到(1,0)(2,0)(3,0)通過比較本身的myid不是最大的,它會從新投票新的投票(3,0)並重新發到集羣中去,對於Server2也同樣,對於Server3來講它不用更新投票信息它比較後本身就是最大的全部再次發出投本身的票就能夠。這樣每一個機器又會收到2個投票信息,Server1會收到Server二、3發來的(3,0)。
每次投票服務器都會進行投票統計,判斷是否有超過半數機器相同的投票信息,對於這三臺服務器來講最終投票結果是(3,0),那麼除了Server3以外其餘都會收到2張(3,0)的投票,這樣在一個3臺集羣中超過半數投票是投給一個機器的,那麼這個機器就是集羣的Leader。
一旦肯定了Leader那麼就須要設置本身的角色以及改變本身的狀態Leader變成LEADING,而Follower就變成FOLLOWING。
服務器運行期間的選舉
當集羣中的服務器數量發生變化時纔會進行從新選舉,好比以前的Leader故障或者新加入一臺Zookeeper服務器。
咱們假設上面的Leader Server3掛了,而後從新選舉
Server1 myid:1 zxid:123
Server2 myid:2 zxid:122
Server3 myid:3 zxid: (宕機)
當集羣感知到Leader掛了,那麼全部Follower角色的服務器就轉變狀態從FOLLOWING變成LOOKING
每一個服務器發出投票Server1會發出(1,123)到集羣中,Server2會發出(2,122)到集羣中,由於第一輪都是投本身。
集羣中可用服務器收到投票
投票處理,這裏和啓動時候使用相同的原則,Server1投票不變由於它的ZXID比Server2的大,因此它再次發一個投本身的票,Server2發現本身的ZXID小因此更新投票信息(1,123)再次發出去
統計投票信息,最終Server1勝出成爲Leader
改變服務器狀態