寫在前面
分布式架構出現后,越來越多的分布式系統會面臨數據一致性的問題。目前,ZooKeeper 是在解決分布式數據一致性上最成熟穩定且被大規模應用的工業級解決方案。
ZooKeeper 保證 分布式系統數據一致性的核心算法就是 ZAB 協議(ZooKeeper Atomic Broadcast,原子消息廣播協議)。
ZAB 協議
ZooKeeper 能夠保證數據一致性主要依賴於 ZAB 協議的 消息廣播,崩潰恢復和數據同步 三個過程。
消息廣播
-
一個事務請求(Write)進來之后,Leader 節點會將寫請求包裝成 Proposal 事務,並添加一個全局唯一的 64 位遞增事務 ID,也就是 Zxid(消息的先后順序就是通過比較 Zxid);
-
Leader 節點向集群中其他節點廣播 Proposal 事務,Leader 節點和 Follower 節點是解耦的,通信都會經過一個 FIFO 的消息隊列,Leader 會為每一個 Follower 節點分配一個單獨的 FIFO 隊列,然后把 Proposal 發送到隊列中;
-
Follower 節點收到對應的 Proposal 之后會把它持久到磁盤上,當完全寫入之后,發一個 ACK 給 Leader;
-
當 Leader 節點收到超過半數 Follower 節點的 ACK 之后(Quorum 機制),會提交本地機器上的事務,同時開始廣播 commit, Follower 節點收到 commit 之后,完成各自的事務提交。
ZAB 協議針對事務請求的處理過程類似於一個兩階段提交過程,第一階段是廣播事務操作,第二階段是廣播提交操作,而在這種兩階段提交模型下,是無法處理因 Leader 節點宕機帶來的數據不一致問題的,比如下面兩種情況:
-
當 Leader(Server1) 發起一個事務 Proposal1 后就宕機了,導致 Follower 都沒有 Proposal1。
-
當 Leader 發起 Proposal2 后收到了半數以上的 Follower 的 ACK,但是還沒來得及向 Follower 節點發送 Commit 消息就宕機了。
為了解決 Leader 宕機以及宕機后導致的數據不一致問題,ZAB 協議引入了崩潰恢復模式。
崩潰恢復模式必須解決以下問題:
-
Server1 恢復過來再次加入到集群中的時候,必須確保丟棄 Proposal1,即保證被丟棄的消息不能再次出現。
-
選舉出的新 Leader 必須擁有集群中所有機器 Zxid 最大的 Proposal,即保證已經被處理的消息不能丟。
崩潰恢復
Zookeeper 集群進入崩潰恢復階段的時機:
集群服務剛啟動時進入崩潰恢復階段選取 Leader 節點。
Leader 節點突然宕機或者由於網絡原因導致 Leader 節點與過半的 Follower 失去了聯系,集群也會進入崩潰恢復模式。
選舉 Leader 節點
首先使用 Leader 選舉算法選出一個新的 Leader 節點。選舉過程如下:
-
各個節點變為 Looking 狀態
Leader 宕機后,余下的 Follower 節點都會將自己的狀態變更為 Looking(注意 Observer 不參與選舉),然后開始進入 Leader 選舉過程。
-
各個 Server 節點都會發出一個投票,參與選舉
在第一次投票中,所有的 Server 都會投自己,然后各自將投票發送給集群中所有機器。
-
集群接收來自各個服務器的投票,開始處理投票和選舉
處理投票的過程就是對比 Zxid 的過程,假定 Server3 的 Zxid 最大,Server1 判斷 Server3 可以成為 Leader,那么 Server1 就投票給 Server3,判斷的依據如下:首先選舉 epoch 最大的,如果 epoch 相等,則選 zxid 最大的,若 epoch 和 zxid 都相等,則選擇 server id 最大的。
在選舉過程中,如果有節點獲得超過半數的投票數,則會成為 Leader 節點,反之則重新投票選舉。 -
選舉成功,各節點的狀態為 Leading 和 Following。
Zab 中的節點有三種狀態,folloing(當前節點是 Follower 節點),leading(當前節點是 Leader 節點),looking/election(當前節點處於選舉狀態);伴隨着的 Zab 協議消息廣播和崩潰恢復兩階段之間的轉換,節點狀態也隨之轉換。
數據同步
崩潰恢復完成選舉以后,接下來的工作就是數據同步,在選舉過程中,通過投票已經確認 Leader 節點是最大 Zxid 的節點,同步階段就是利用 Leader 前一階段獲得的最新 Proposal 歷史同步集群中所有的副本。
總結
ZAB 協議是 CAP 理論中 CP 的典型實現,其崩潰恢復階段涉及到的 Leader 節點選舉過程和數據同步選舉完成后的數據同步過程都是對外不提供服務的,就是為了保證數據的強一致性犧牲了可用性。到這里,關於 ZooKeeper 使用 ZAB 協議保證分布式系統下數據一致性已經分析完了,有關於 Paxos 算法以及 ZAB 協議與 Paxos 算法之間的聯系這里不做詳細分析,有興趣的小伙伴可以查閱《從 Paxos 到 ZooKeeper 分布式一致性原理與實戰》這本書,里面有詳細的介紹。
參考
《從 Paxos 到 ZooKeeper 分布式一致性原理與實戰》
《分布式技術原理與實戰 45 講》