1. 程式人生 > 實用技巧 >zookeeper的ZAB演算法

zookeeper的ZAB演算法

ZAB(ZooKeeper Atomic Broadcast)是為ZooKeeper設計的一種支援崩潰恢復的原子廣播協議。

ZAB和Paxos最大的不同是,ZAB主要是為分散式主備系統設計的,而Paxos的實現是一致性狀態機(state machine replication)

儘管ZAB不是Paxos的實現,但是ZAB也參考了一些Paxos的一些設計思想,比如:

  • leader向follows提出提案(proposal)
  • leader 需要在達到法定數量(半數以上)的follows確認之後才會進行commit
  • 每一個proposal都有一個紀元(epoch)號,類似於Paxos中的選票(ballot)

ZAB特性

  • 一致性保證
    1. 可靠提交(Reliable delivery) -如果一個事務 A 被一個server提交(committed)了,那麼它最終一定會被所有的server提交
    2. 全域性有序(Total order) - 假設有A、B兩個事務,有一臺server先執行A再執行B,那麼可以保證所有server上A始終都被在B之前執行
    3. 因果有序(Causal order) - 如果傳送者在事務A提交之後再發送B,那麼B必將在A之後執行
  • 只要大多數(法定數量)節點啟動,系統就行正常執行
  • 當節點下線後重啟,它必須保證能恢復到當前正在執行的事務

ZAB的具體實現

  • ZooKeeper由client、server兩部分構成
  • client可以在任何一個server節點上進行讀操作
  • client可以在任何一個server節點上發起寫請求,非leader節點會把此次寫請求轉發到leader節點上。由leader節點執行
  • ZooKeeper使用改編的兩階段提交協議來保證server節點的事務一致性

ZXID

ZooKeeper會為每一個事務生成一個唯一且遞增長度為64位的ZXID,ZXID由兩部分組成:低32位表示計數器(counter)和高32位的紀元號(epoch)。epoch為當前leader在成為leader的時候生成的,且保證會比前一個leader的epoch大
實際上當新的leader選舉成功後,會拿到當前叢集中最大的一個ZXID,並去除這個ZXID的epoch,並將此epoch進行加1操作,作為自己的epoch。

歷史佇列(history queue)

每一個follower節點都會有一個先進先出(FIFO)的佇列用來存放收到的事務請求,保證執行事務的順序

可靠提交由ZAB的事務一致性協議保證
全域性有序由TCP協議保證
因果有序由follower的歷史佇列(history queue)保證

ZAB工作模式

  • 廣播(broadcast)模式
  • 恢復(recovery)模式

廣播(broadcast)模式

  • leader從客戶端收到一個寫請求
  • leader生成一個新的事務併為這個事務生成一個唯一的ZXID,
  • leader將這個事務傳送給所有的follows節點
  • follower節點將收到的事務請求加入到歷史佇列(history queue)中,併發送ack給ack給leader
  • 當leader收到大多數follower(超過法定數量)的ack訊息,leader會發送commit請求
  • 當follower收到commit請求時,會判斷該事務的ZXID是不是比歷史佇列中的任何事務的ZXID都小,如果是則提交,如果不是則等待比它更小的事務的commit

恢復模式

恢復模式大致可以分為四個階段

  • 選舉
  • 發現
  • 同步
  • 廣播
  1. 當leader崩潰後,叢集進入選舉階段,開始選舉出潛在的新leader(一般為叢集中擁有最大ZXID的節點)
  2. 進入發現階段,follower與潛在的新leader進行溝通,如果發現超過法定人數的follower同意,則潛在的新leader將epoch加1,進入新的紀元。新的leader產生
  3. 叢集間進行資料同步,保證叢集中各個節點的事務一致
  4. 叢集恢復到廣播模式,開始接受客戶端的寫請求

當 leader在commit之後但在發出commit訊息之前宕機,即只有老leader自己commit了,而其它follower都沒有收到commit訊息 新的leader也必須保證這個proposal被提交.(新的leader會重新發送該proprosal的commit訊息)

當 leader產生某個proprosal之後但在發出訊息之前宕機,即只有老leader自己有這個proproal,當老的leader重啟後(此時左右follower),新的leader必須保證老的leader必須丟棄這個proprosal.(新的leader會通知上線後的老leader截斷其epoch對應的最後一個commit的位置)

腦裂

ZAB為解決腦裂問題,要求叢集內的節點數量為2N+1, 當網路分裂後,始終有一個叢集的節點數量過半數,而另一個節點數量小於N+1, 因為選主需要過半數節點同意,所以任何情況下叢集中都不可能出現大於一個leader的情況。



作者:孫成醬子說
連結:https://www.jianshu.com/p/400a44edee88
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。