分佈式理論(七)—— 一致性協議之 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 相似。設計

  1. 那麼複製過程又是如何的呢?複製過程相似 2PC,ZAB 只須要 Follower 有一半以上返回 Ack 信息就能夠執行提交,大大減少了同步阻塞。也提升了可用性。

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

2. 消息廣播

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

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

1.將數據都複製到 Follwer 中排序

image.png

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

image.png

  1. 當超過半數成功迴應,則執行 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 協議就介紹到這裏,篇幅有限,不免疏漏。

good luck!!!!

引用

《從 Paxos 到 Zookeeper——分佈式一致性原理和實踐》

相關文章
相關標籤/搜索