上篇文章《zookeeper-一個關於paxos的故事-《每日五分鐘搞定大數據》》說到zab是在paxos的基礎上作了重要的改造,解決了一系列的問題,這一篇咱們就來講下這個zab。算法
zab協議的全稱是ZooKeeper Atomic Broadcast即zookeeper「原子」「廣播」協議。它規定了兩種模式:崩潰恢復和消息廣播服務器
恢復模式
何時進入?微信
當整個服務框架在啓動過程當中網絡
當Leader服務器出現網絡中斷崩潰退出與重啓等異常狀況架構
當有新的服務器加入到集羣中且集羣處於正常狀態(廣播模式),新服會與leader進行數據同步,而後進入消息廣播模式app
這三種狀況ZAB都會進入恢復模式框架
幹了什麼?分佈式
選舉產生新的Leader服務器,同時集羣中已有的過半的機器會與該Leader完成狀態同步,這些工做完成後,ZAB協議就會退出崩潰恢復模式大數據
廣播模式
何時進入?url
集羣狀態穩定,有了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 )。
而後發起proposal給follower,Leader 會爲每個 Follower 都各自分配一個單獨的隊列,而後將須要廣播的事務 Proposal 依次放入這些隊列中去,而且根據 FIFO策略進行消息發送。
每個 Follower 在接收到這個事務 Proposal 以後,都會首先將其以事務日誌的形式寫入到本地磁盤中去,而且在成功寫入後反饋給 Leader 服務器一個 Ack 響應。
當 Leader 服務器接收到超過半數 Follower 的 Ack 響應後,就會廣播一個Commit 消息給全部的 Follower 服務器以通知其進行事務提交,同時 Leader 自身也會完成對事務的提交。
推薦閱讀
zookeeper-操做與應用場景-《每日五分鐘搞定大數據》
zookeeper-架構設計與角色分工-《每日五分鐘搞定大數據》
zookeeper-一個關於paxos的故事-《每日五分鐘搞定大數據》
最近這幾篇理論性的東西太多,下一篇寫點簡單的代碼,zookeeper分佈式鎖的實現。感謝閱讀。歡迎關注公衆號:大叔據!
本文分享自微信公衆號 - 老懞大數據(simon_bigdata)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。