淺談Zookeeper之分佈式一致性協議:ZAB協議

啥是ZAB協議?

ZAB其實就是Zookeeper Atomic Broadcast,也就是zookeeper原子廣播,是zookeeper用來保持分佈式事務一致性的一種協議

ZAB其實就是定義了zookeeper集羣在運行過程中的一些通信準則,包括像信息同步,選舉,故障轉移等機制的一些實現。

ZAB協議的內容其實主要包括兩個模塊:消息廣播崩潰恢復

消息廣播

當zookeeper集羣在正常進行的時候,各個結點之間需要保持最終一致性,此時就需要消息廣播機制。

在zookeeper集羣中,節點分爲一個leader節點和若干個follower節點。當Client向集羣發送請求時,該請求有可能落在集羣中的任何一個節點上(當然,準確來說不是全部,在啓動zookeeper-cli的時候可以指定若干個節點的 ip:port,請求只會落在這些節點上),這個節點如果是leader的話,那麼直接對該請求進行處理,如果該節點是follower的話,那麼follower還需要把該請求轉發給集羣中的leader,讓leader來處理

所以,該請求最終都會落在leader上,leader收到該請求,會將該請求解析成一個對應的事務proposql,同時爲該proposql分配一個全局唯一且遞增的id(zxid),該id爲64位的值,高32位爲epoch,低32位爲自增值。

img

epoch是一個與選舉相關的自增數字,整個zookeeper集羣每經歷一次選舉,epoch的值就+1

而低32位,每次選舉完一次後就歸零,然後自增,以此來保證事務id在全局的遞增(這一點在進行崩潰恢復的時候很重要)

而生成這個事務proposql之後,leader就會將該事務持久化到磁盤中,leader會爲每個follower都維護一個單獨的FIFO(先來先服務)隊列,將該事務加入隊列中進行發送,以此來保證全局順序性。follower收到之後,就會將該事務持久化到磁盤中,然後向leader發送一個ack。當leader收到超過半數的follower發來的ack後,就可以向它們發送commit指令,然後follower們進行commit

是不是有點像兩階段提交?確實很像,但和兩階段提交最大的區別就是,兩階段階段中,leader必須收到所有follower的ack,而在zookeeper的ZAB中,只需要收到過半的ack即可進行ack

崩潰恢復

如果所有的集羣在整個服務期間都能正常運行而不發生崩潰就好了~但這可能嘛?(哭

很明顯是不可能的,所以跟大多數集羣一樣,zookeeper集羣也應該有故障轉移和恢復的機制,主要是針對leader節點的崩潰而進行的。有三種情況會觸發leader

選舉

恢復的方法也很簡單,重新選舉出一個新的leader不就好了?用的也是類似於paxos算法的思想,各個節點進行多輪投票,然後互相交換投票,再根據zxid修改投票,然後進行下一輪投票,直到過半的票數都指向同一個節點,那麼該節點就成爲了leader。

選舉原則大致爲
1)epoch 最大的
2)若 epoch 相等,選 zxid 最大的
3)若 epoch 和 zxid 都相等,則選擇 server_id 最大的(也就是zoo.cfg中的myid)

發現

選出一個leader之後,下一步就是發現階段。發現階段其實主要就是收集follower最近接受的事務,爲下一步的數據同步作準備

並且可以肯定的是,選出來的這個leader擁有最大的zxid,爲啥要選出一個擁有最大zxid的節點呢?考慮這兩種情況:

同步

  • leader節點生成了事務proposql,且持久化到了磁盤中,然後還沒來得及發送給follower們,就宕機了
  • leader節點收到了過半的ack,commit還沒發送,就宕機了

對於情況一,需要對這種事務進行丟棄;而對情況二,需要對follower進行協同,使得全部follower都變成提交狀態

那爲什麼要選一個zxid最大的節點作爲leader就清楚了,其實以上兩種情況如果發生了,那麼最大zxid的那個事務就是出問題的那個事務,根據這個事務的執行程度來進行協同,最後保證最終一致性即可。

選舉完了,協同完了,那下一步幹啥?此時集羣已經恢復到正常情況了,所以直接切換成消息廣播模式,進行信息同步即可

所以,總結一下,崩潰恢復分爲三步:1.選舉 2.同步 3.同步 4.切換爲廣播模式

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