zab協議的全稱是ZooKeeper Atomic Broadcast即zookeeper“原子”“廣播”協議。它規定了兩種模式:崩潰恢復和消息廣播
恢復模式
什么時候進入? 當整個服務框架在啟動過程中
當Leader服務器出現網絡中斷崩潰退出與重啟等異常情況
當有新的服務器加入到集群中且集群處于正常狀態(廣播模式),新服會與leader進行數據同步,然后進入消息廣播模式
這三種情況ZAB都會進入恢復模式
干了什么?
選舉產生新的Leader服務器,同時集群中已有的過半的機器會與該Leader完成狀態同步,這些工作完成后,ZAB協議就會退出崩潰恢復模式
廣播模式
什么時候進入?
集群狀態穩定,有了leader且過半機器狀態同步完成,退出崩潰恢復模式后進入消息廣播模式
干了什么?
正常的消息同步,把日常產生數據從leader同步到learner的過程
總結一下zab協議規定的兩種模式在實際操作中經歷了三個步驟,如上圖,下面我再詳細地說下這兩個過程都干了些什么
1.崩潰恢復狀態 - 即選主過程
進入崩潰恢復模式說明集群目前是存在問題的了,那么此時就需要開始一個選主的過程。
zookeeper使用的默認選主算法是FastLeaderElection,它是標準的Fast Paxos算法實現,可解決LeaderElection選舉算法收斂速度慢的問題(上篇文章也有提到過)。
zab協議規定的狀態
LOOKING 當前集群沒有leader,準備選舉
FOLLOWING 已經存在leader,當前服務器為跟隨者
LEADING 唯一的領導,維護與Follower間的心跳
OBSERVING 觀察者狀態。表明當前服務器角色是Observer
投票流程
投票的依據
投票的依據就是下面的兩個id,投票即是給所有服務器發送 (myid,zxid) 信息
myid:用戶在配置文件中自己配置,每個節點都要配置的一個唯一值,從1開始往后累加。
zxid:zxid有64位,分成兩部分:
高32位是Leader的epoch:選舉時鐘,每次選出新的Leader,epoch累加1
低32位是在這輪epoch內的事務id:對于用戶的每一次更新操作集群都會累加1。
注意:zk把epoch和事務id合在一起,每次epoch變化,都將低32位的序號重置,這樣做是為了方便對比出最新的數據,保證了zxid的全局遞增性。(其實這樣也會存在問題,云主機,雖然概率小,這里就先不說了后面的文章會詳細講)。
關于發送選票
第一輪投給自己,之后每個服把上述所有信息發送給其他所有服,票箱中只會記錄每一投票者的最后一票
關于接收投票
服務器會嘗試從其它服務器獲取投票,并記入自己的投票箱內。如果無法獲取任何外部投票,域名注冊,則會確認自己是否與集群中其它服務器保持著有效連接。如果是,則再次發送自己的投票;如果否,則馬上與之建立連接。
關于選舉輪次
由于所有有效的投票都必須在同一輪次中。每開始新一輪投票自身的logicClock自增1。
接收到的logicClock大于自己的。說明自己落后了,更新logicClock后正常。 接收到的logicClock小于自己的。忽略該票。 接收到的logickClock與自己的相等,正常判斷。 關于選票判斷
對比自身的和接收到的(myid,zxid)
首先對比zxid高32位的選舉時鐘epoch 一致則對比zxid低32的事務id 仍然一致則對比用戶自己配置的myid
選完后廣播選出的(myid,zxid)
關于選舉結束
過半服務器選了同一個,則投票結束,根據投票結果更新自身狀態為leader或者follower
還有兩個問題
上面說過zookeeper是一個原子廣播協議,在這個崩潰恢復的過程就體現了它的原子性,zookeeper在選主過程保證了兩個問題:
commit過的數據不丟失
未commit過的數據丟棄
(myid,zxid)的選票設計剛好解決了這兩個問題。
commit過的數據半數以上參加選舉的follwer都有,而且成為leader的條件是要有最高事務id即數據是最新的。
未commit過的數據只存在于leader,但是leader宕機無法參加首輪選舉,epoch會小一輪,最終數據會丟棄。
2.消息廣播狀態 - 即數據同步
如上圖,client端發起請求,讀請求由follower和observer直接返回,寫請求由它們轉發給leader。
Leader 首先為這個事務分配一個全局單調遞增的唯一事務ID (即 ZXID )。