Zookeeper經過ZAB保證分佈式事務的最終一致性。算法
ZAB全稱Zookeeper Atomic Broadcast(ZAB,Zookeeper原子消息廣播協議)數據庫
1.ZAB是一種專門爲Zookeeper設計的一種支持 崩潰恢復 的 原子廣播協議 ,是Zookeeper保證數據一致性的核心算法。ZAB借鑑了Paxos算法,但它不是通用的一致性算法,是特別爲Zookeeper設計的。服務器
2.基於ZAB協議,Zookeeper實現了⼀種主備模式的系統架構來保持集羣中各副本之間的數據的⼀致性,表現形式就是使⽤⼀個單⼀的主進程(Leader服務器)來接收並處理客戶端的全部事務請求(寫請求),並採⽤ZAB的原⼦⼴播協議,將服務器數據的狀態變動爲事務 Proposal的形式⼴播到全部的Follower進程中。網絡
問題提出架構
ZAB過程框架
ZAB協議的核⼼是 定義了對於那些會改變Zookeeper服務器數據狀態的事務請求的處理⽅式
全部事務必須由一個 全局惟一的服務器來協調處理 ,這樣的服務器被稱爲Leader服務器,餘下的服務器則稱爲Follower服務器分佈式
1.Leader服務器負責將一個客戶端事務請求轉化爲一個事務Proposal(提案),並將該Proposal分發給集羣中全部的Follower服務器url
2.Leader服務器等待全部Follower服務器的反饋,一旦超過半數的Follower服務器進行了正確的反饋後,Leader就會向全部的Follower服務器發送Commit消息,要求將前一個Proposal進行提交。設計
ZAB協議內容簡介3d
ZAB協議包括兩種基本的模式: 崩潰恢復 和 消息廣播
消息廣播
當集羣中有過半的Follower服務器完成了和Leader服務器的狀態同步,那麼整個服務框架就能夠進入 消息廣播模式 。
當一臺遵照ZAB協議的服務器啓動後加入到集羣中,若是此時集羣中已經存在一個Leader服務器在負責進行消息廣播,那麼加入的服務器會自覺的進入 數據恢復模式:找到Leader 所在的服務器,並與其進⾏數據同步,數據同步完成後參與到消息⼴播流程中。
ZAB協議的消息廣播使用原子廣播協議, 相似一個二階段提交的過程 ,但又有所不一樣。
1.二階段提交中,須要全部參與者反饋ACK後再發送Commit請求。要求全部參與者要麼成功,要麼失敗。這樣會產生嚴重的阻塞問題;
2.ZAB協議中,Leader等待半數以上的Follower成功反饋ACK便可,不須要收到所有的Follower反饋ACK。
消息廣播過程:
1.客戶端發起寫請求
2.Leader將客戶端請求信息轉化爲事務Proposal,同時爲每一個Proposal分配一個事務ID(Zxid)
3.Leader爲每一個Follower單獨分配一個FIFO的隊列,將須要廣播的Proposal依次放入到隊列中
4.Follower接收到Proposal後,首先將其以事務日誌的方式寫入到本地磁盤中,寫入成功後給Leader反饋一個ACK響應
5.Leader接收到半數以上Follower的ACK響應後,即認爲消息發送成功,能夠發送Commit消息
6.Leader向全部Follower廣播Commit消息,同時自身也會完成事務提交。Follower接收到Commit消息後也會完成事務的提交
崩潰恢復
在整個服務框架啓動過程當中,若是Leader服務器出現網絡中斷、崩潰退出或重啓等異常狀況,ZAB協議就會進入崩潰恢復模式。同時選舉出新的Leader服務器。
當選舉產生了新的Leader服務器,同時集羣中已經有過半的機器與該Leader服務器完成了狀態同步(數據同步)以後,ZAB協議會退出恢復模式。
1.在ZAB協議中,爲了保證程序的正確運⾏,整個恢復過程結束後須要選舉出⼀個新的Leader 服務器。
2.Leader選舉算法不只僅須要讓Leader⾃身知道已經被選舉爲Leader,同時還須要讓集羣中的全部其餘機器也可以快速地感知到選舉產⽣出來的新Leader服務器。
ZAB保證數據一致性
ZAB協議規定了 若是⼀個事務Proposal在⼀臺機器上被處理成功,那麼應該在全部的機器上都被處理成功,哪怕機器出現故障崩潰。 針對這些狀況ZAB協議須要保證如下條件:
已經在Leader服務器上提交的事務最終被全部服務器都提交。
假設⼀個事務在 Leader 服務器上被提交了,而且已經獲得過半 Folower 服務器的Ack反饋,可是在它 將Commit消息發送給全部Follower機器以前,Leader服務器掛了
丟棄只在Leader服務器上被提出(未提交)的事務。
假設初始的 Leader 服務器 Server1 在提出了⼀個事務Proposal3 以後就崩潰退出 了,從⽽致使集羣中的其餘服務器都沒有收到這個事務Proposal3。因而,當 Server1 恢復過來再次加 ⼊到集羣中的時候,ZAB 協議須要確保丟棄Proposal3這個事務。
綜上所述,ZAB的選舉出來的Leader必須知足如下條件:
可以確保提交已經被 Leader 提交的事務 Proposal,同時丟棄已經被跳過的事務 Proposal。即:
1.新選舉出來的 Leader 不能包含未提交的 Proposal。
2.新選舉的 Leader 節點中含有最大的 zxid 。
ZAB如何數據同步
全部正常運行的服務器要麼成爲Leader,要麼成爲Follower並和Leader保持同步。
1.完成Leader選舉(新的 Leader 具備最高的zxid)以後,在正式開始⼯做(接收客戶端請求)以前,Leader服務器會⾸先確認事務⽇志中的全部Proposal是否都已經被集羣中過半的機器提交了,即 是否完成數據同步 。
2.Leader服務器須要確保全部的Follower服務器可以接收到每⼀條事務Proposal,而且可以正確地將全部已經提交了的事務Proposal應⽤到內存數據中。等到 Follower服務器將全部其還沒有同步的事務 Proposal 都從 Leader 服務器上同步過來併成功應⽤到本地數據庫中後,Leader服務器就會將該Follower服務器加⼊到真正的可⽤Follower列表中,並開始以後的其餘流程。
ZAB運行時狀態#
ZAB協議設計中,每一個進程都有可能處於以下三種狀態之一:
ZAB狀態的切換
啓動時的狀態轉換
1.全部進程的初始狀態都是LOOKING狀態,此時不存在Leader。
2.接下來,進程會試圖選舉出來一個新的Leader,Leader切換爲LEADING狀態,其它進程發現已經選舉出新的Leader,那麼它就會切換到FOLLOWING狀態,並開始與Leader保持同步。
3.處於FOLLOWING狀態的進程稱爲Follower,LEADING狀態的進程稱爲Leader。
4.當Leader崩潰或者放棄領導地位時,其他的Follower進程就會切換到LOOKING狀態開始新一輪的Leader選舉。
運行過程當中的狀態轉換
一個Follower只能和一個Leader保持同步,Leader進程和全部的Follower進程之間經過心跳監測機制來感知彼此的狀況。
1.若Leader可以在超時時間內正常的收到心跳檢測,那麼Follower就會一直與該Leader保持鏈接。
2.若是在指定時間內Leader沒法從過半的Follower進程那裏接收到心跳檢測,或者TCP鏈接斷開,那麼Leader會放棄當前週期的領導,並轉換爲LOOKING狀態;其餘的Follower也會選擇放棄這個Leader,同時轉換爲LOOKING狀態,以後會進行新一輪的Leader選舉
ZAB的四個階段
選舉階段(Leader Election)
節點在一開始都處於選舉階段,只要有一個節點超過半數階段的票數,它就能夠當選準Leader,只有到達第三個階段(同步階段),這個準Leader纔會成爲真正的Leader。
這一階段的目的就是爲了選出一個準Leader,而後進入下一階段。
發現階段
在這個階段中,Followers和上一輪選舉出的準Leader進行通訊,同步Followers最近接受的事務Proposal。這個階段主要目的是發現當前大多數節點接受的最新提議,而且準Leader生成新的epoch,讓Followers接受,更新它們的acceptedEpoch。
一個Follower只會鏈接一個Leader,若是有一個節點F認爲另外一個Follower P是Leader,F在嘗試鏈接P時會被拒絕,F被拒絕後,就會進入選舉階段。
同步階段
同步階段主要是利用 Leader 前一階段得到的最新 Proposal 歷史,同步集羣中全部的副本。
只有當 quorum(超過半數的節點) 都同步完成,準 Leader 纔會成爲真正的 Leader。Follower 只會接收 zxid 比本身 lastZxid 大的 Proposal。
廣播階段
到了這個階段,Zookeeper 集羣才能正式對外提供事務服務,而且 Leader 能夠進行消息廣播。同時,若是有新的節點加入,還須要對新節點進行同步。須要注意的是,Zab 提交事務並不像 2PC 同樣須要所有 Follower 都 Ack,只須要獲得 quorum(超過半數的節點)的Ack 就能夠。
ZAB協議實現
Java 版本的ZAB協議的實現跟上面的定義略有不一樣,選舉階段使用的是 Fast Leader Election(FLE),它包含了步驟2的發現職責。由於FLE會選舉擁有最新提議的歷史節點做爲 Leader,這樣就省去了發現最新提議的步驟。
實際的實現將 發現和同步階段合併爲 Recovery Phase(恢復階段) ,因此,Zab 的實現實際上有三個階段。
快速選舉(Fast Leader Election)
前面提到的 FLE 會選舉擁有最新Proposal history (lastZxid最大)的節點做爲 Leader,這樣就省去了發現最新提議的步驟。 這是基於擁有最新提議的節點也擁有最新的提交記錄
成爲Leader的條件:
1.選epoch最大的
2.epoch相等,選zxid最大的
3.epoch和zxid都相等,選server_id最大的(zoo.cfg 中配置的 myid)
節點在選舉開始時,都默認投票給本身,當接收其餘節點的選票時,會根據上面的 Leader條件 判斷而且更改本身的選票,而後從新發送選票給其餘節點。當有一個節點的得票超過半數,該節點會設置本身的狀態爲 Leading ,其餘節點會設置本身的狀態爲 Following。
恢復階段(Recovery Phase)
這一階段 Follower 發送他們的 lastZxid 給 Leader,Leader 根據 lastZxid 決定如何同步數據。這裏的實現跟前面的 階段 3 有所不一樣:Follower 收到 TRUNC 指令會終止 L.lastCommitedZxid 以後的 Proposal ,收到 DIFF 指令會接收新的 Proposal。
history.lastCommittedZxid:最近被提交的提議的 zxid history.oldThreshold:被認爲已經太舊的已提交提議的 zxid
廣播階段(Broadcast Phase)
參考 4.1 [ZAB協議內容#消息廣播]
ZAB與Paxos的聯繫和區別
聯繫
1.都存在一個相似Leader進程的角色,由其負責協調多個Follower進程的運行
2.Leader進程都會等待超過半數的Follower做出正確的反饋後,纔會將一個提議進行提交(過半原則)
3.在ZAB中,每一個Proposal中都包含了一個epoch值,用來表明當前Leader週期,在Paxos中一樣存在這樣的一個表示,名字爲 Ballot。
區別
1.Paxos算法中,新選舉產生的主進程會進行兩個階段的工做;第一階段稱爲讀階段:新的主進程和其餘進程通訊來收集主進程提出的提議,並將它們提交。第二階段稱爲寫階段:當前主進程開始提出本身的提議。
2.ZAB協議在Paxos基礎上添加了同步階段,此時,新的Leader會確保存在過半的Follower已經提交了以前Leader週期中的全部事物Proposal。這一同步階段的引入,可以有效保證,Leader在新的週期中提出事務Proposal以前,全部的進程都已經完成了對以前全部事務Proposal的提交。
總的來講,ZAB協議和Paxos算法的本質區別在於二者的設計目的不同:ZAB協議主要用於構建一個高可用的分佈式數據主備系統,而Paxos算法則用於構建一個分佈式的一致性狀態機系統。
總結
問題解答:
1.主從架構下,leader 崩潰,數據一致性怎麼保證?
leader 崩潰以後,集羣會選出新的 leader,而後就會進入恢復階段,新的 leader 具備全部已經提交的提議,所以它會保證讓 followers 同步已提交的提議,丟棄未提交的提議(以 leader 的記錄爲準),這就保證了整個集羣的數據一致性。
2.選舉 leader 的時候,整個集羣沒法處理寫請求的,如何快速進行 leader 選舉?
這是經過 Fast Leader Election 實現的,leader 的選舉只須要超過半數的節點投票便可,這樣不須要等待全部節點的選票,可以儘早選出 leader。