[ZooKeeper研究]二 ZooKeeper協議介紹

前面介紹了ZooKeeper的基本知識,這一節咱們介紹一下ZooKeeper使用的協議。只有瞭解了ZooKeeper的協議,才能更好得理解ZooKeeper源代碼的實現。ZooKeeper使用的是Zab(ZooKeeper Atomic Broadcast)協議,它是基於Paoxs算法實現的。因此這一節咱們按照這個順序來說解:html

  • Paoxs算法
  • Zab協議

  

Paoxs算法算法

首先看一下Paoxs算法,通常說到zookeeper,咱們都會提起Paoxs算法Lesile Lamport.promise

Paoxs算法是zookeeper的靈魂,這個算法是Leslie Lamport在1990年提出的一種基於消息傳遞的一致性算法.Paxos 算法解決的問題是一個分佈式系統如何就某個值(決議)達成一致。在ZooKeeper中的應用場景就是Leader選舉。安全

該算法由Leslie於1990年在文章The Part-Time Parliament中首次提出,可是這篇文章至關的晦澀難懂(也有一些軼事,能夠看文章連接中Leslie本身寫的內容),因而,Lesilie在2001年寫下了Paxos Made Simple.他對此解釋道:app

At the PODC 2001 conference, I got tired of everyone saying how difficult it was to understand the Paxos algorithm, published in [122]. Although people got so hung up in the pseudo-Greek names that they found the paper hard to understand, the algorithm itself is very simple. So, I cornered a couple of people at the conference and explained the algorithm to them orally, with no paper. When I got home, I wrote down the explanation as a short note, which I later revised based on comments from Fred Schneider and Butler Lampson. The current version is 13 pages long, and contains no formula more complicated than n1 > n2. less

Paxos Made Simple的abstract只有一句話:分佈式

The Paxos algorithm, when presented in plain English, is very simple.ide

在上文中是這樣描述Paoxs算法執行過程的:性能

Phase 1.優化

(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors.

(b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered proposal (if any) that it has accepted.

Phase 2.

(a) If the proposer receives a response to its prepare requests (numbered n) from a majority of acceptors, then it sends an accept request to each of those acceptors for a proposal numbered n with a value v, where v is the value of the highest-numbered proposal among the responses, or is any value if the responses reported no proposals.

(b) If an acceptor receives an accept request for a proposal numbered n, it accepts the proposal unless it has already responded to a prepare request having a number greater than n.

這幾乎就是Paxos的所有了.  這裏就不一句一句翻譯了。

 

Zab協議

Zab是一個高性能的廣播協議,主要用於主備系統,它是專門爲ZooKeeper設計的。Zab協議的詳細內容請參考論文《Zab: High-performance broadcast for primary-backup systems》。

ZAB相比Paxos的優勢有:

  • 狀態一致性保證,爲了保證狀態一致性,Zookeeper提出了兩個安全屬性(Safety Property) :
    • 全序(Total order):若是消息a在消息b以前發送,則全部Server應該看到相同的結果。
    • 因果順序(Causal order):若是消息a在消息b以前發生(a致使了b),並被一塊兒發送,則a始終在b以前被執行。
  • 更高效得從失敗中恢復。狀態一致性保證了多個ZooKeeper客戶端同時進行多個事務操做的正確性。因此當一個leader掛掉以後,新的leader只須要從選舉它的一個多數派中得到當前最大的事務號做爲它的恢復點,這樣leader最多隻須要跟具備最大的事務號的那一個進程(若是有多個,因爲狀態一致性保證,隨機挑一個便可)同步便可。而在Paoxs中,因爲同一個事務(這裏其實是指序列號)能夠有多個不一樣的投票,不一樣的進程對於同一個事務可能接受不一樣的值,因此不能簡單的使用事務號來選擇恢復點,新的leader須要找到當前最大的事務號,而後對於它已經commit的事務號跟這個最大的事務號之間的每個事務號都須要從新執行一遍Phase1獲得最終commit的值,這樣的恢復過程 複雜並且不夠高效。

   Paxos的一致性不能達到ZooKeeper的要求。由於Paoxs只是保證最終一致性,若是處理的請求之間有依賴關係,利用Paoxs處理的時候可能知足不了這些依賴關係。舉個例子:假設一開始Paxos系統中的leader是P1,它發起了兩個事務<t1, v1>(表示序號爲t1的事務要寫的值是v1)和<t2, v2>,過程當中掛了。新來個leader是P2,它發起了事務<t1, v1'>。然後又來個新leader是P3,它彙總了一下,得出最終的執行序列<t1, v1'>和<t2, v2>,即P2的t1在前,P1的t2在後。對應到ZooKeeper中的操做,P1對應的事務t1要建立"/a",事務t2要建立"/a/test",而P2的事務t1要建立"/b",P3彙總了以後得出的結論是先建立"/b",再建立"/a/test"。而對於ZooKeeper中的建立操做,只有父節點已經存在的狀況下才能建立子節點,也即只有先成功建立了"/a",接下來建立"/a/test"才能成功,因此建立完"/b"以後再建立"/a/test"就會失敗,這不是咱們但願的結果。

  爲了保證這一點,ZAB要保證同一個leader的發起的事務要按順序被apply,同時還要保證只有先前的leader的全部事務都被apply以後,新選的leader才能發起新的事務。ZAB的核心思想,形象的說就是保證任意時刻只有一個節點是leader,全部更新事務都由leader發起去更新全部複本(稱爲follower),更新時用的就是兩階段提交協議,只要多數節點prepare成功,就通知他們commit。各follower要按當初leader讓他們prepare的順序來apply事務。由於ZAB處理的事務永遠不會回滾,ZAB的2階段提交作了點優化,多個事務只要通知zxid最大的那個commit,以前的各follower會通通commit。

  

  

  剩下的就是怎麼來保證leader的可靠性,由於leader是會crash的,因此引入了leader選舉機制。leader選舉是基於Paoxs協議的,成爲leader的條件是必需要有一個多數派支持,此外還須要知道如下知識:

  • leader跟follower之間經過心跳來檢測異常;
  • follower檢測到leader心跳異常以後,會從新發起leader選舉,一個follower若試圖成爲新的leader,首先要得到一個多數派的支持,而後從狀態最新的節點同步事務,完成後纔可正式成爲leader發起新的事務;

   Leader選舉遇到的最大問題是:新Leader是否要繼續老Leader的狀態。這裏要按老Leader Crash的時機分兩種狀況:

  • 老Leader在COMMIT前Crash(已經提交到本地)
  • 老Leader在COMMIT後Crash,但有部分Follower接收到了Commit請求

  第一種狀況,這些數據只有老Leader本身知道,當老Leader重啓後,須要與新Leader同步並把這些數據從本地刪除,以維持狀態一致。

  第二種狀況,新Leader應該能經過一個多數派得到老Leader提交的最新數據。

  老Leader重啓後,可能還會認爲本身是Leader,可能會繼續發送未完成的請求,從而由於兩個Leader同時存在致使算法過程失敗,ZooKeeper的解決辦法是把Leader信息加入每條消息的id中,Zookeeper中稱爲zxid,zxid爲一64位數字,高32位爲leader信息又稱爲epoch,每次leader轉換時遞增;低32位爲消息編號,Leader轉換時應該從0從新開始編號。經過zxid,Follower能很容易發現請求是否來自老Leader,從而拒絕老Leader的請求。

 

綜上可見,Zab協議實際上仍是基於Paoxs衍生出來的,Paoxs中沒有保證請求之間的邏輯順序,只考慮數據的全序,Zab在這方面進行了完善補充,同時因爲leader的存在,簡化了Paoxs的二段提交爲一段提交(Phase2),最後爲了確保leader的可靠性,又基於Paoxs協議實現了leader的選舉機制。

相關文章
相關標籤/搜索