ZooKeeper 一致性協議 ZAB 原理,瞭解一下

一致性協議有很多種,比如 Paxos,Raft,2PC,3PC等等,在這講一種協議,ZAB 協議,該協議應該是所有一致性協議中生產環境中應用最多的了。爲什麼?因爲它是爲 Zookeeper 設計的分佈式一致性協議!

1. 什麼是 ZAB 協議? ZAB 協議介紹

  1. ZAB 協議全稱:Zookeeper Atomic Broadcast(Zookeeper 原子廣播協議)。
  2. Zookeeper 是一個爲分佈式應用提供高效且可靠的分佈式協調服務。在解決分佈式一致性方面,Zookeeper 並沒有使用 Paxos ,而是採用了 ZAB 協議。
  3. ZAB 協議定義:ZAB 協議是爲分佈式協調服務 Zookeeper 專門設計的一種支持****崩潰恢復和原子廣播協議。下面我們會重點講這兩個東西。
  4. 基於該協議,Zookeeper 實現了一種主備模式的系統架構來保持集羣中各個副本之間 數據一致性。具體如下圖所示:

image.png

上圖顯示了 Zookeeper 如何處理集羣中的數據。所有客戶端寫入數據都是寫入到 主進程(稱爲 Leader)中,然後,由 Leader 複製到備份進程(稱爲 Follower)中。從而保證數據一致性。從設計上看,和 Raft 類似。

那麼複製過程又是如何的呢?

複製過程類似 2PC,ZAB 只需要 Follower 有一半以上返回 Ack 信息就可以執行提交,大大減小了同步阻塞。也提高了可用性。

簡單介紹完,開始重點介紹消息廣播崩潰恢復整個 Zookeeper 就是在這兩個模式之間切換。 簡而言之,當 Leader 服務可以正常使用,就進入消息廣播模式,當 Leader 不可用時,則進入崩潰恢復模式。

2. 消息廣播

ZAB 協議的消息廣播過程使用的是一個原子廣播協議,類似一個 二階段提交過程。對於客戶端發送的寫請求,全部由 Leader 接收,Leader 將請求封裝成一個事務 Proposal,將其發送給所有 Follwer ,然後,根據所有 Follwer 的反饋,如果超過半數成功響應,則執行 commit 操作(先提交自己,再發送 commit 給所有 Follwer)。

基本上,整個廣播流程分爲 3 步驟:

1、將數據都複製到 Follwer 中

image.png

2、等待 Follwer 迴應 Ack,最低超過半數即成功

image.png

3、當超過半數成功迴應,則執行 commit ,同時提交自己

image.png

通過以上 3 個步驟,就能夠保持集羣之間數據的一致性。實際上,在 Leader 和 Follwer 之間還有一個消息隊列,用來解耦他們之間的耦合,避免同步,實現異步解耦。

還有一些細節:

  1. Leader 在收到客戶端請求之後,會將這個請求封裝成一個事務,並給這個事務分配一個全局遞增的唯一 ID,稱爲事務ID(ZXID),ZAB 兮協議需要保證事務的順序,因此必須將每一個事務按照 ZXID 進行先後排序然後處理。
  2. 在 Leader 和 Follwer 之間還有一個消息隊列,用來解耦他們之間的耦合,解除同步阻塞。
  3. zookeeper集羣中爲保證任何所有進程能夠有序的順序執行,只能是 Leader 服務器接受寫請求,即使是 Follower 服務器接受到客戶端的請求,也會轉發到 Leader 服務器進行處理。
  4. 實際上,這是一種簡化版本的 2PC,不能解決單點問題。等會我們會講述 ZAB 如何解決單點問題(即 Leader 崩潰問題)。

3. 崩潰恢復

剛剛我們說消息廣播過程中,Leader 崩潰怎麼辦?還能保證數據一致嗎?如果 Leader 先本地提交了,然後 commit 請求沒有發送出去,怎麼辦?

實際上,當 Leader 崩潰,即進入我們開頭所說的崩潰恢復模式(崩潰即:Leader 失去與過半 Follwer 的聯繫)。下面來詳細講述。

假設1:Leader 在複製數據給所有 Follwer 之後崩潰,怎麼辦? 假設2:Leader 在收到 Ack 並提交了自己,同時發送了部分 commit 出去之後崩潰怎麼辦?

針對這些問題,ZAB 定義了 2 個原則:

  1. ZAB 協議確保那些已經在 Leader 提交的事務最終會被所有服務器提交。
  2. ZAB 協議確保丟棄那些只在 Leader 提出/複製,但沒有提交的事務。

所以,ZAB 設計了下面這樣一個選舉算法:能夠確保提交已經被 Leader 提交的事務,同時丟棄已經被跳過的事務。

針對這個要求,如果讓 Leader 選舉算法能夠保證新選舉出來的 Leader 服務器擁有集羣總所有機器編號(即 ZXID 最大)的事務,那麼就能夠保證這個新選舉出來的 Leader 一定具有所有已經提交的提案。 而且這麼做有一個好處是:可以省去 Leader 服務器檢查事務的提交和丟棄工作的這一步操作。

image.png

這樣,我們剛剛假設的兩個問題便能夠解決。假設 1 最終會丟棄調用沒有提交的數據,假設 2 最終會同步所有服務器的數據。這個時候,就引出了一個問題,如何同步?

4. 數據同步

當崩潰恢復之後,需要在正式工作之前(接收客戶端請求),Leader 服務器首先確認事務是否都已經被過半的 Follwer 提交了,即是否完成了數據同步。目的是爲了保持數據一致。

當所有的 Follwer 服務器都成功同步之後,Leader 會將這些服務器加入到可用服務器列表中。

實際上,Leader 服務器處理或丟棄事務都是依賴着 ZXID 的,那麼這個 ZXID 如何生成呢?

答:在 ZAB 協議的事務編號 ZXID 設計中,ZXID 是一個 64 位的數字,其中低 32 位可以看作是一個簡單的遞增的計數器,針對客戶端的每一個事務請求,Leader 都會產生一個新的事務 Proposal 並對該計數器進行 + 1 操作。

而高 32 位則代表了 Leader 服務器上取出本地日誌中最大事務 Proposal 的 ZXID,並從該 ZXID 中解析出對應的 epoch 值,然後再對這個值加一。

image.png

高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事務的唯一性。同時,也能讓 Follwer 通過高 32 位識別不同的 Leader。簡化了數據恢復流程。

基於這樣的策略:當 Follower 鏈接上 Leader 之後,Leader 服務器會根據自己服務器上最後被提交的 ZXID 和 Follower 上的 ZXID 進行比對,比對結果要麼回滾,要麼和 Leader 同步。

5. 總結

到了總結的時刻了。

ZAB 協議和我們之前看的 Raft 協議實際上是有相似之處的,比如都有一個 Leader,用來保證一致性(Paxos 並沒有使用 Leader 機制保證一致性)。再有采取過半即成功的機制保證服務可用(實際上 Paxos 和 Raft 都是這麼做的)。

ZAB 讓整個 Zookeeper 集羣在兩個模式之間轉換,消息廣播和崩潰恢復,消息廣播可以說是一個簡化版本的 2PC,通過崩潰恢復解決了 2PC 的單點問題,通過隊列解決了 2PC 的同步阻塞問題。

而支持崩潰恢復後數據準確性的就是數據同步了,數據同步基於事務的 ZXID 的唯一性來保證。通過 + 1 操作可以辨別事務的先後順序。關於 ZAB 協議就介紹到這裏,篇幅有限,難免疏漏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章