ZAB協議介紹

什麼是Zab協議

ZAB協議,全稱 Zookeeper Atomic Broadcast(Zookeeper 原子廣播協議)。它是專門爲分佈式協調服務——Zookeeper,設計的一種支持崩潰恢復和原子廣播的協議。

從設計上看,ZAB協議和 Raft 很類似。ZooKeeper集羣中,只有一個Leader節點,其餘均爲Follower節點。

整個ZAB協議一共定義了三個階段:

  • 發現:要求zookeeper集羣必須選舉出一個 Leader 進程,同時 Leader 會維護一個 Follower 可用客戶端列表。將來客戶端可以和這些 Follower節點進行通信。
  • 同步:Leader 要負責將本身的數據與 Follower 完成同步,做到多副本存儲。這樣也是提現了CAP中的高可用和分區容錯。Follower將隊列中未處理完的請求消費完成後,寫入本地事務日誌中
  • 廣播:Leader 可以接受客戶端新的事務Proposal請求,將新的Proposal請求廣播給所有的 Follower。

三個階段執行完爲一個週期,在Zookeeper集羣的整個生命週期中,這三個階段會不斷進行,如果Leader崩潰或因其它原因導致Leader缺失,ZAB協議會再次進入階段一。

Zab協議核心

Zab協議的核心:定義了事務請求的處理方式

  1. 所有的事務請求必須由一個全局唯一的服務器來協調處理,這樣的服務器被叫做 Leader服務器。其他剩餘的服務器則是 Follower服務器。
  2. Leader服務器 負責將一個客戶端事務請求,轉換成一個 事務Proposal,並將該 Proposal 分發給集羣中所有的 Follower 服務器,也就是向所有 Follower 節點發送數據廣播請求(或數據複製)
  3. 分發之後Leader服務器需要等待所有Follower服務器的反饋(Ack請求),在Zab協議中,只要超過半數的Follower服務器進行了正確的反饋後(也就是收到半數以上的Follower的Ack請求),那麼 Leader 就會再次向所有的 Follower服務器發送 Commit 消息,要求其將上一個 事務proposal 進行提交。

Zab協議內容

Zab 協議包括兩種基本的模式:崩潰恢復 和 消息廣播

崩潰恢復

一旦 Leader 服務器出現崩潰或者由於網絡原因導致 Leader 服務器失去了與過半 Follower 的聯繫,那麼就會進入崩潰恢復模式。

前面我們說過,崩潰恢復具有兩個階段:Leader 選舉與初始化同步。當完成 Leader 選 舉後,此時的 Leader 還是一個準 Leader,其要經過初始化同步後才能變爲真正的 Leader。

初始化同步

具體過程如下:

  1. 爲了保證 Leader 向 Learner 發送提案的有序,Leader 會爲每一個 Learner 服務器準備一 個隊列;
  2. Leader 將那些沒有被各個 Learner 同步的事務封裝爲 Proposal;
  3. Leader 將這些 Proposal 逐條發給各個 Learner,並在每一個 Proposal 後都緊跟一個 COMMIT 消息,表示該事務已經被提交,Learner 可以直接接收並執行
  4. Learner 接收來自於 Leader 的 Proposal,並將其更新到本地;
  5. 當 Learner 更新成功後,會向準 Leader 發送 ACK 信息;
  6. Leader 服務器在收到來自 Learner 的 ACK 後就會將該 Learner 加入到真正可用的 Follower 列表或 Observer 列表。沒有反饋 ACK,或反饋了但 Leader 沒有收到的 Learner,Leader 不會將其加入到相應列表。

恢復模式的兩個原則

當集羣正在啓動過程中,或 Leader 與超過半數的主機斷連後,集羣就進入了恢復模式。 對於要恢復的數據狀態需要遵循兩個原則。

1. 已被處理過的消息不能丟

當 Leader 收到超過半數 Follower 的 ACKs 後,就向各個 Follower 廣播 COMMIT 消息, 批准各個 Server 執行該寫操作事務。當各個 Server 在接收到 Leader 的 COMMIT 消息後就會在本地執行該寫操作,然後會向客戶端響應寫操作成功。

但是如果在非全部 Follower 收到 COMMIT 消息之前 Leader 就掛了,這將導致一種後 果:部分 Server 已經執行了該事務,而部分 Server 尚未收到 COMMIT 消息,所以其並沒有 執行該事務。當新的 Leader 被選舉出,集羣經過恢復模式後需要保證所有 Server 上都執行 了那些已經被部分 Server 執行過的事務。

2. 被丟棄的消息不能再現

當在 Leader 新事務已經通過,其已經將該事務更新到了本地,但所有 Follower 還都沒 有收到 COMMIT 之前,Leader 宕機了(比前面敘述的宕機更早),此時,所有 Follower 根本 就不知道該 Proposal 的存在。當新的 Leader 選舉出來,整個集羣進入正常服務狀態後,之 前掛了的 Leader 主機重新啓動並註冊成爲了 Follower。若那個別人根本不知道的 Proposal 還保留在那個主機,那麼其數據就會比其它主機多出了內容,導致整個系統狀態的不一致。 所以,該 Proposa 應該被丟棄。類似這樣應該被丟棄的事務,是不能再次出現在集羣中的, 應該被清除。

消息廣播

當集羣中的 Learner 完成了初始化狀態同步,那麼整個 zk 集羣就進入到了正常工作模式 了。

如果集羣中的 Learner 節點收到客戶端的事務請求,那麼這些 Learner 會將請求轉發給 Leader 服務器。然後再執行如下的具體過程:

  1. Leader 接收到事務請求後,爲事務賦予一個全局唯一的 64 位自增 id,即 zxid,通過 zxid 的大小比較即可實現事務的有序性管理,然後將事務封裝爲一個 Proposal。
  2. Leader 根據 Follower 列表獲取到所有 Follower,然後再將 Proposal 通過這些 Follower 的 隊列將提案發送給各個 Follower。
  3. 當 Follower 接收到提案後,會先將提案的 zxid 與本地記錄的事務日誌中的最大的 zxid 進行比較。若當前提案的 zxid 大於最大 zxid,則將當前提案記錄到本地事務日誌中,並 向 Leader 返回一個 ACK。
  4. 當 Leader 接收到過半的 ACKs 後,Leader 就會向所有 Follower 的隊列發送 COMMIT 消息,向所有 Observer 的隊列發送 Proposal。
  5. 當 Follower 收到 COMMIT 消息後,就會將日誌中的事務正式更新到本地。當 Observer 收到 Proposal 後,會直接將事務更新到本地。
  6. 無論是 Follower 還是 Observer,在同步完成後都需要向 Leader 發送成功 ACK。

zookeeper的選舉和同步其實都依賴於一個點,也就是事務的id(zxid)。如果其中一個server的zxid是最大,說明當前的server處理的事務是最新的,那麼這個server可以在leader服務器崩潰的時候,作爲下一次的leader進行記錄。當新的leader被選舉出來的時候,它也是根據zxid來進行同步。因爲follower的zxid肯定不如它。

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