模擬Paxos算法及其簡單學習總結

1、導讀

Paxos算法的流程自己不算很難,可是其推導過程和證實比較難懂。在Paxos Made Simple[1]中雖然也用了儘可能簡化的流程來解釋該算法,但其實仍是比較抽象,並且有一些細節問題沒有交代,讀完也只能瞭解到算法的一個大體輪廓。在《從Paxos到Zookeeper 分佈式一致性原理與實踐》[3]中也講到Paxos算法,可是其行文思路也是延續了原論文,沒有一個具體的實例來幫助讀者理解。html

第一次我也沒看懂,後來以爲,多是我學習的方式不對。一般而言,都是在已經成熟的問題抽象和邏輯推理之上去理解算法的,理論層面的概念模型爲算法賦予靈魂,但每每不夠具體於是不易理解;相對而言,恰當的算法模擬能夠爲賦予算法血肉,理解算法最好的方式就是手動模擬。兩方面都很重要,適當結合每每可以理解得更深入。本文也試圖先梳理Paxos算法的流程,而後特地構造一些實例去模擬算法的場景,從實例的角度去理解該算法。算法

本文省略掉沒必要要的基礎的介紹,儘可能直接的進入主題。內容範圍僅限於the The Basic Paxos Algorithm,不討論Paxos算法家族的其餘變種。接下來的第二節是針對各角色的信息保持、算法流程的梳理和簡單約定,在第三節會構造一些實例,並結合算法流程去模擬該算法,第四節會簡單總結該算法重要特性,在最後會引入一些參考資料。promise

2、信息保持及算法流程

2.1 關於提案及Acceptor和Proposer的信息保持安全

首先這裏的提案(proposal)是一個抽象的概念。具體能夠是「推選某個節點爲Leader」或者「將某個值更新爲另外一個值」,甚至是「將某個更新操做更寫到日誌系統中」等等。網絡

在後面的算法模擬中,提案由一個提案編號和提案值(Value)組成:[N,Value]。Paxos算法以輪次的形式進行,也即每輪以一個全局惟一的自增編號發起。輪次與提案編號呼應,即在第K輪次中,在知足必定條件的狀況下會產生編號爲K,提案值爲VK的提案:[K,VK]。less

若是某個提案在某輪次中被某超過半數的Acceptor批准,則該提案被選定。異步

其次Acceptor和Proposer都須要保持一些必要的信息,並會更新這些信息。分佈式

Acceptor保持的信息爲:RoP_Max,RoA_Max和Value_Acc。學習

其中:ui

RoP_Max含義是某Acceptor參與的最大輪次(the max round of participation),至關於原論文中的rnd[a],初始爲0。

RoA_Max的含義是某Acceptor已批准的提案的最大輪次(the max round of acceptance),至關於原論文中的vrnd[a],初始值爲0。

Value_Acc表明被當前已批准的提案,至關於原論文中的vval[a],初始爲NULL。

注意:這裏參與的含義多是在P1-B階段Acceptor對某倫次提案請求的響應,也多是在P2-B階段Acceptor批准了某輪次的提案,所以這兩個階段均會更新RoP_Max。

不可貴知,這裏的RoA_Max和Value_Acc組合能夠獲得某倫次被批准的提案:[RoA_Max,Value_Acc]。

其初始狀態以下:

 

Proposer保存的信息爲R_Max和Value_Pick。

其中:

R_Max表示某Proposer發起的最大輪次號,至關於原論文中的crnd[c],初始值爲0。

Value_Pick表示Proposer在P2-A階段挑選的提案值,至關於原論文中的cval[c],初始值爲NULL。

R_Max和Value_Pick組合可產生一個提案:[R_Max,Value_Pick],固然不是每輪都具有條件產生一個提案。

其初始狀態以下:

2.2原論文中的算法流程

Paxos Made Simple[1]中算法流程分爲兩階段:

Phase 1:
(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors.-->記做P1-A
(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.-->記做P1-B

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.-->記做P2-A
(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.-->P2-B

上述四個階段能夠分別簡記爲:P1-A,P1-B,P2-A,P2-B。

以上算法流程提供了一個初步的算法輪廓,有不少細節問題沒有交代。所以僅僅依靠以上的信息,並不可以徹底去模擬出一個具體的算法實例。

Fast Paxos[2]中的Section 2:The Classic Paxos Algorithm中做者給出了一個比較具體的算法流程(少數單詞已根據本文語境作替換):

P1-A:
If R_Max < i, then proposer starts round i by setting R_Max to i,setting Value_Pick to NULL, and sending a message to each acceptor a requesting that a participate in round i.
P1-B:
If an acceptor a receives a request to participate in round i and i > RoP_Max, then a sets RoP_Max to i and sends proposer p a message containing the round number i and the current values of RoA_Max and Value_Acc.
If i <= RoP_Max (so a has begun round i or a higher-numbered round), then a ignores the request.

P2-A:
If R_Max = i (so p has not begun a higher-numbered round),Value_Pick = NULL (so p has not yet performed phase 2a for this round), and p has received phase 1b messages for round i from a majority of the acceptors; then by a rule described below, p uses the contents of those messages to pick a value v, sets Value_Pick to v,and sends a message to the acceptors requesting that they vote in round i to accept v.
P2-B:
If an acceptor a receives a request to vote in round i to accept a value v, and i >= RoP_Max and RoA_Max != i; then a votes in round i to accept v, sets RoA_Max and RoP_Max to i, sets Value_Acc to v, and sends a message to all learners announcing its round i vote.
If i < RoP_Max or RoA_Max = i (so a has begun a higher-numbered round or already voted in this round), then a ignores the request.

 以上流程應該是比較精確的描述,英文自己的內容也不難理解,再也不須要過多的翻譯。本文也會遵循這個流程去模擬一些實例。

2.3 本文對算法流程的約定。

爲方便後文的陳述,對以上各階段中涉及的過程作恰當的約定,同時儘可能與大多數介紹Paxos算法的文章說法保持一致。

一、爲方便起見,各階段的消息通訊以(X)或者(X,[Y,Z])或者([Y,Z])的形式表示,具體視狀況而定。

二、P1-A中Proposer向Acceptor集合發送的提案請求稱做Prepare請求,消息內容包括輪次號N:(N)。

三、P1-B中Acceptor的響應Proposer的過程稱做Promise響應,消息內容包含輪次號和某提案(=提案編號+提案值):(N,[K,VK])。

其中N的含義是Acceptor向Proposer保證該本身不會批准(Accept)任何編號小於N的提案。

四、P2-A中Proposer向Acceptor集合發送批准請求稱做Accept請求,消息內容是一個提案:([K,VK])。

3、實例及算法模擬

3.1 一個最基礎實例

假設有5個Acceptor,1個Proposer。其初始狀態下如上文中的列表所示。

1)按照P1-A約定,Proposer發起輪次爲1 的Prepare請求;

2)假設全部Acceptor均收到請求,按照約定P1-B,知足1大於全部Acceptor持有的RoP_Max值的條件,因而將本身的RoP_Max值設置爲1,全部的Acceptor均響應Prepare請求,此時全部的Acceptor以前並未批准任何提案。

 3)假設Proposer收到了全部的5個Acceptor的Promise響應,按照P2-A的約定,收到響應的數量已經超過Acceptor集合的半數,同時因爲以前並未存在批准的提案,Proposer能夠任意選擇一個提案值,這裏暫且記爲選擇了V1這個提案,Proposer應該發送Accept請求,但願Acceptor集合批准該提案。

 

4)假設全部Acceptor均收到了Accept請求,按照P2-B的約定,5個Acceptor還沒有參與任何編號比1更大的提案(此時只存在一個Proposer且以前只發起了一輪提案),因此全部Acceptor應該批准V1這個提案,批准以後Acceptor的狀態以下:

 

至此,[1,V1]這個提案被半數以上的Acceptor批准,因此[1,V1]是一個被選定(chosen)的提案,V1是被選定的提案值。

3.2 異常狀況下算法的工做流程

上一小節的基礎實例是在理想狀況下的情形,而實際狀況要複雜不少,例如網絡擁塞致使消息延遲或者亂序、網絡分化致使消息不可達、Acceptor和Proposer自己宕機等等,這些異常狀況要求該算法要有比較好的容錯性。實際上整個分佈式系統設計討論的幾個核心要點之一就是針對各類異常狀況下的系統容錯性。

如下討論一些典型的異常狀況下Paxos算法如何正確的工做。

仍然假設有5個Acceptor,1個Proposer。

1)初始狀態

Acceptor集合持有狀態:

 

 Proposer持有狀態:

 2)Proposer發起第一輪Prepare請求;假設因爲暫時網絡中斷或者網絡分化等網絡異常,只有Acceptor1和Acceptor5收到了提案請求,這兩個Acceptor正常響應Prepare請求。

3)Proposer收到了這兩個響應,此時根據P2-A的約定,響應數不足半數,不具有發送Accept請求的條件,因而Proposer從新發起第二輪Prepare請求。假定此次有四個Acceptor收到了請求,惟獨發往Acceptor1的請求丟失了。成功收到消息的四個Acceptor給予正常響應。

 

4)Proposer也成功收到了四個響應,根據P2-A的約定,Proposer任選一個提案V1發送Accept請求:(2,V1)。可是Acceptor集合中只有Acceptor2和Acceptor3兩個收到了這個Accept請求。此時[2,V1]只被兩個Acceptor批准,目前爲止仍然沒有任何一個提案被選定。

5)Proposer發起第三輪提案Prepare請求,所有的Acceptor收到了提案請求,並給予響應。 

6)Proposer收到所有的響應,應該評估這些響應,並從中響應的提案中挑選一個提案值。此時根據P2-A的約定,挑選的應該是最大的RoA_Max所對應的提案值。max{0,2,2,0,0}=2,對應的提案是V1,所以Proposer在本輪挑選的提案值爲V1。Proposer向Acceptor集合發送Accept請求:[3,V1],假設此次有Acceptor1,Acceptor3和Acceptor5收到了Accept請求並批准了該提案。

到目前爲止,進過3輪,[3,V1]提案已經被超過半數的Acceptor批准,所以被選定。其實上述討論的過程當中,每一個過程都有可能存在消息丟失,而消息丟失的緣由也多是多種多樣,並不只僅指因網絡緣由形成的消息丟失,例如節點短期宕機也能夠歸爲這裏的消息丟失。

實際上,在網路通訊狀況較差的狀況下,即使進過多輪次,仍然有可能得不到一個選定的提案,不管是3個Acceptor仍是5個Acceptor或者說更多的Acceptor構成的集合,能夠很容易的構造出這樣的場景,關鍵是Acceptor接受提案的環節(P2-B階段)直接影響了該算法的最終結果。

 3.3 關於時序問題

以上雖然只是討論了只有一個Proposer的情形,而且是假定了每輪結束後(來自Acceptor的響應不足半數以上或者在Acceptor集合批准某提案後仍然不能選定某個提案)才發起下一輪的提案請求。實際上,兩輪提案徹底能夠容許異步進行,基於該算法Acceptor集合在P1-B和P2-B對提案編號的斷定和約束,若是Acceptor在Promise響應(對於P1-B)或者接受(對應P2-B)某輪次爲M的提案時,發現本身在以前已經響應了比M更大輪次的提案,則M這一輪次的提案實際上已經失效了,被更高輪次的提案所搶佔。因此只要保證一個全局不重複的提案編號(輪次編號),按照該算法的約定,就可以保證該算法的正確性,但可能須要進行更多輪次才能選定一個提案。

更進一步,若是存在多個Proposer的狀況,每一個Proposer多都能在任意時間點發起提案請求,彷佛有可能出現上面提到的「輪次搶佔」的現象。好比多個Proposer若是按照必定的節拍交疊地在P1-B這個階段輪流「搶佔」,會出現所謂的「活鎖」現象。

3.4 「活鎖」現象

若是容許同一個Proposer交疊的發起提案請求,考慮以下一種情形:

如上圖所示,不一樣的顏色表明同一個Proposer在不一樣時間點發起的不一樣輪次。全部的輪次均在P2-B階段被Acceptor集合認爲無效,由於在收到該輪次的Accept請求以前不久,Acceptor集合響應了一個更高輪次的提案,致使RoP_Max變大。若是一直按照這個節拍發起後續的輪次,那麼陷入一個「死循環」,永遠沒法選定一個提案了,儘管在真實的場景中這種狀況發生的機率很小。

儘管理論上存在這種狀況,可是實際上能夠很容易的對Proposer施加約束來規避這種狀況。例如能夠約定針對某個Proposer發起的某一輪次的提案請求,只有肯定該輪次爲無效被丟棄後,同一個Proposer才能發起下一輪次的提案請求。

理解了上述過程,在多個Proposer存在時致使「活鎖」現象與之相似,很容易構造一個場景來重現「活鎖」現象,只須要讓不一樣的Proposer輪流發起提案請求便可,以下所示。

3.5 關於Pcik a Value規則

假設在第K輪次,提案[K,VK]被超過半數的Acceptor批准,那麼這個提案就認爲被選定,而且在之後的輪次M(M>K)中,根據挑選Value的規則,在P2-A階段,Proposer只可以挑選VK,所以只能組成[M,VK]形式的提案但願Acceptor集合批准。

所以,即便在多輪Paxos算法過程當中,有可能會存在多個提案被選定,可是這些被選定的提案值一定是相等的。從某種角度來講,要達到要取得一致意見,達成共識的目的,實際上要求的是針對某提案值Value達成共識,而提案編號爲提案值披上了一層外衣,使咱們更好的進行算法的處理。

原論文中關於Pcik a Value的規則以下:

Pcik a Value的規則能夠說是該算法的核心,也是保證了該算法安全性的關鍵。

假設有3個Acceptor,一個Proposer,此次以某一箇中間狀態開始討論。

Acceptor當前狀態(達到這種狀態是徹底有可能的):

1)Aroposer以N=3發起第三輪Prepare請求:(3),Acceptor1和Acceptor3收到請求,並做出響應。

2)Proposer成功收到響應,發起Accept請求:[3,V1],但只有Acceptor1和Acceptor3收到了Accept請求,知足批准條件。 

 

此時,提案[3,V1]已經被Acceptor1和Acceptor3批准,被視爲選定的提案。而後若是再以N=4發起新一輪的提案請求,在第4輪的P1-B階段,Proposer只有在收到2個Promise響應的條件下才具有發起Accept請求的條件。而根據Pick a Value的規則,不管怎麼組合兩個Promise響應,其RoA_Max最大值只能是3,其對應的Value只能是V1,只能是V1有資格被挑選出來在P2-A階段與輪次4組成新的提案:[4,V1],不多是V2。V1在第4輪結束後定會被超過半數的Acceptor批准,這一狀況沒法被改變。

討論更通常地狀況:

不失通常性,這裏假設在順利完成第K輪提案以後,提案[K,VK]被超過半數Acceptor批准從而首次被選定,在1到K-1的各輪次中,還沒有有一個提案被選定。

那麼在第K輪的P1-B階段,一定有超過半數的Acceptor響應了Proposer的Prepare請求,響應Prepare請求的集合中每一個Acceptor都將本身的RoP_Max更新爲K。

Proposer也一定收到了超過半數的Promise響應,不然沒法發起Accept請求。而後Proposer挑選了VK,順利發起了Accept請求:([k,VK])。(注意:由於前面已經設立了第K輪後VK被選定的題設,故這裏Accept請求中一定是VK無疑,VK並不是特指某一個提案,能夠是任意一個,具備任意性。)

超過半數的Acceptor收到Accept請求,更新本身的RoP_Max和RoA_Max爲K,Value爲VK,而後VK被批准的數量超過半數,被選定。

至此,其實已經有了一些隱含其中的細微邏輯能夠發掘。考慮將RoA_Max=K的Acceptor集合記爲集合S,將Value=VK的集合記爲集合T。顯然,兩個過半的集合一定有重疊,至少重疊一個。「超過半數」的發現對於接下來的推論其實很重要。

 接下來發起第K+1輪的Prepare請求:(K+1),假設這一輪也很順利。

Proposer收到超過半數Acceptor的Promise響應,記這些半數以上的Acceptor集合爲Q。此時能夠判定,全部的這些Promise響應中,由RoA_Max組成的集合中最大值一定爲K,由於集合S與集合Q的交集一定至少有一個公共元素。同時,這個RoA_Max=K的Promise響應中Value一定爲VK,由於這就是在第K輪被集合S中每一個Acceptor批准的提案。所以根據P2-A的約定,第K+1輪被挑選出來的Value是VK,該輪產生的提案是[K+1,VK],發送該提案但願Acceptor可以批准,固然在該輪的P2-B階段,可能沒有一個Acceptor批准VK(全部消息均丟失),也有可能某些Acceptor批准了VK。總之,通過第K+1輪以後,批准VK的Acceptor不會比第K輪減小,只會愈來愈多。

按照以上的邏輯,繼續往更高的輪次推演,超過半數的Acceptor批准VK這個結論已然成立,由此保證該算法的安全性。

固然以上邏輯只是一個直白的、非正式的推理,但可以說明部分問題。更精準的證實能夠看論文。

3.6 Learner學習被選定的提案

Learner學習的目的就是須要找出某一個超過半數的Acceptor批准的提案。要實現這一目的,最簡單的辦法是一旦Acceptor批准了一個提案,就將該批准的提案告知每個Learner,顯然從通訊次數的角度來看,這樣有點麻煩,至少須要Count(Acceptor)XCount(Learner)次通訊才能肯定被選定的。

稍微改進一下,能夠選一個主Learner(原文中稱做a distinguished learner),Acceptor只須要與這個主Learner通訊,再由這個主Learner去通知其餘的Learner。這種改進方法存在單點故障,缺少可靠性。因此一般,須要一個主Learner的集合來解決可靠性的問題。

4、一點總結

1)Paxos算法在網絡通訊比較好的狀況下可以快速高效的讓一個提案被半數以上的Acceptor接受,選定一個提案,從而達成一致意見。

2)Paxos算法的容錯能力是2F+1。即在總共有2F+1個服務端的狀況,只要不超過F個服務端同時出現損毀,該算法就可以正常運做。

2)採用「超過半數」的機制,保證在某輪次只能有一個提案沒選定,採用Pick a Value規則挑選提案值,保證不一樣的輪次只能有一個提案值被選定。不一樣的輪次可能有不一樣的提案被選定,可是這些選定的提案僅僅是提案編號不一樣,其提案值一定相同。

4)當某個提案被選定,那麼今後之後,全部的Acceptor只能批准該提案值,這是由Pick a Value的規則保障的。

5)假設全部的Acceptor都接批准某個提案值,將這些提案值的集合記爲S(例如S={V1,V2,V3}),那麼,即便如今還沒有有提案值被選定,可是能夠確定,在未來被選定的提案值必定是集合S中的某一個提案值,毫不多是其餘的提案值了,保證了一種「封閉」特性。保證這個特性的正是P1-B中Acceptor響應給Proposer時的約束:Acceptor只會將本身曾經批准的提案中最高編號的提案響應給Proposer。舉例來講,對於5個Acceptor來講,排除冗餘狀況,Proposer最多隻有三次可以任選提案值的機會(收到全部的Promise響應中均爲NULL而且Accept請求存在消息丟失),考慮任選提案值也有可能會選擇到相同的提案值,所以集合S最多隻能有三個不一樣的提案值。更通常的,當Acceptor集合的大小爲奇數R時,集合S的大小最多爲R/2+1。

5、 Reference

[1] Leslie Lamport. Paxos made simple.2001,11,1

[2] Leslie Lamport.Fastpaxos. DistributedComputing,19(2):79–103,2006.

[3] 《從Paxos到Zookeeper 分佈式一致性原理與實踐》

[4] 《分佈式系統原理介紹 劉傑》

[5] http://www.infoq.com/cn/articles/wechat-paxosstore-paxos-algorithm-protocol

完!

轉載請註明原文:http://www.cnblogs.com/qcblog/p/8727556.html

相關文章
相關標籤/搜索