ZAB協議簡介


Zookeeper 使用 Zookeeper Atomic Broadcast (ZAB) 協議來保障分布式數據一致性。

ZAB是一種支持崩潰恢復的消息廣播協議,采用類似2PC的廣播模式保證正常運行時性能,並使用基於 Paxos 的策略保證崩潰恢復時的一致性。

在閱讀本文前建議先了解2PC和Paxos

ZAB協議中節點存在四種狀態:

  • Leading: 當前節點為集群 Leader,負責協調事務
  • Following: 當前節點為 Follower 在 Leader 協調下執行事務
  • Looking: 集群沒有正在運行的 Leader, 正處於選舉過程
  • Observing: 節點跟隨 Leader 保存系統最新的狀態提供讀服務,但不參與選舉和事務投票

因為 Observing 節點不參與事務和選舉,因此下文所述節點不包括 Observing 節點

ZAB協議存在兩種工作模式:

  • 廣播模式: 當集群正常運行過程中,Leader 使用廣播模式保證各 Follower 節點的一致性
  • 恢復模式: 集群啟動或 Leader 崩潰時系統進入恢復模式,選舉 Leader 並將集群中各節點的數據同步到最新狀態

Zookeeper 集群中每個節點都會存儲系統數據的完整副本,可以獨立處理讀請求。

當 Follower 收到寫請求時會將其轉發給 Leader, Leader 為每個寫請求分配唯一的全局有序的事務ID(Zookeeper Transaction Id, ZXID)。

Leader 在廣播模式下協調各 Follower 完成事務,並保證集群更新到一致的狀態。

一致性保證

ZAB協議保證集群的順序一致性而不保證強一致性。

即 Leader 依次完成兩個事務 A、B 時,不能保證所有 Follower 立即更新到最新狀態(不保證強一致性); 只保證所有 Follower 一定時間內會同步到最新狀態(保證最終一致性),且任意 Follower 都認為事務A先於事務B完成,不會亂序(保證全局順序一致性)。

此外,ZAB協議保證來自同一個 Follower 的兩個事務 A、B 按照 Follower 發出請求的順序(而非 Leader 收到請求的順序)依次執行,不會出現亂序。即保證任意客戶端寫請求的一致性。

ZXID

ZXID 是 Zookeeper 集群中事務的唯一標識,保證全局有序。

ZXID 是一個 64 位整數, 高32位為周期號(epoch), 每個 Leader 被選舉后都會增加 epoch 與上任 Leader 區分。低32位是 Leader 開始事務時分配的遞增編號。

ZXID 中的 epoch 可以保證 Leader 崩潰重新選舉后被丟棄的事務不會繼續執行。

廣播模式

廣播模式是一個移除了中斷邏輯的2PC協議:

  1. Leader 收到寫請求后為其分配一個 ZXID 並生成提案發送給所有 Follower
  2. Follower 收到提案后寫事務日志但不提交,成功后返回 ACK 告知 Leader 可以進行提交。
  3. Leader 收到過半 Follower 的 ACK 響應后發出 commit 請求執行提交
  4. Leader 收到過半 Follower 對 commit 請求的 ACK 響應后便認為事務已完成。剩余的 Follower 則會放棄執行此次事務,進入數據同步階段,與集群達成一致。

ZAB廣播模式相對於完整的2PC移除了中斷邏輯, 且只要過半 Follower 完成即可不需要等待全部 Follower。

崩潰或網絡超時的 Follower 可以直接拋棄 Leader,並在數據同步階段與集群達成一致,這種做法提高了集群的性能。

因為無法保證所有 Follower 都完成了提交,所以 Zookeeper 無法保證強一致性。

Leader 為每個 Follower 的寫請求維護了一個 FIFO 隊列以保證順序一致性,具體實現方式是根據 TCP 報文的序列號確定請求的先后順序。

恢復模式

當集群啟動或者Leader崩潰時,Zookeeper 集群會進入恢復模式選舉新的 Leader 並將集群同步至最新狀態。

Leader 與過半的 Follower 無法正常通信即視為崩潰

在崩潰恢復過程中需要保證:

  • 已執行的事務不能丟失(Never forget delivered messages)
  • 未執行的事務不能繼續執行(Let go of messages that are skipped)

若 Leader 在 commit 階段崩潰,根據已完成的事務不能丟失的原則,這些事務應該繼續完成。

因為集群中 ZXID 最大的提案是 Leader 崩潰前發出的最新的提案,所以應選擇擁有 ZXID 最大的提案的節點做為新的 Leader。

新 Leader 會將自身日志中所有未提交事務重新生成提案並協調集群將其完成, 保證所有被發送的消息(delivered messages)都被處理。

若 Leader 在 proposal 階段崩潰,根據未執行的事務不能繼續的原則,節點應當丟棄這些事務。

當新 Leader 被選舉之后會增加 ZXID 的 epoch 值,因此 epoch 值較小的提案可以直接丟棄。

恢復模式分為兩個階段:選舉階段和恢復階段。

上文已經說明恢復階段的任務是 Leader 將未提交事務重新生成提案並協調集群將其完成,不再贅述。

選舉過程

選舉要保證:

  • 集群中有且只有一個節點作為 Leader, 該 Leader 可以與集群中過半節點通信
  • 新 Leader 擁有 ZXID 最大的提案

在3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection選舉算法

每張選票包含3條信息:

  • vote_sid: 推舉的服務器ID
  • vote_zxid: 推舉的服務器的最大ZXID
  • epoch: 投票的輪數

發起選舉的節點會向所有可通信節點發送第一張選票,推舉自己作為 Leader。

收到選票的服務器根據下列規則決定自己的投票:

  • 若 epoch 大於自身 epoch 說明上一輪投票已結束,更新自身 epoch 值加入新一輪投票,並清除已結束輪次的數據。
  • 選擇自身已知 擁有最大ZXID 的服務器作為 Leader。即服務器本地保存(vote_sid, vote_zxid)並初始化為自身(sid, zxid), 若收到的選票中 vote_zxid 更大就更新本地數據,並根據最新數據投出選票。
  • 若存在 zxid 相同則選擇 sid 最大的服務器(作者認為選擇sid最小的也可以)。

若在某輪投票中某個節點收到過半數的相同選票,那么認為該服務器為新的 Leader 投票結束。

因為選舉階段要求服務器收到過半選票才能成為新 Leader, 因此不可能出現集群中存在兩個 Leader 的現象。

選舉過程是比較典型的 Paxos 算法過程,選舉過程中不會產生新的 ZXID, 因此不會出現 Paxos 算法中活鎖的現象。


關於ZAB協議的詳細內容可以閱讀官方論文ZooKeeper’s atomic broadcast protocol: Theory and practice


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM