Paxos算法

參考:
https://my.oschina.net/linlifeng/blog/78918
http://blog.csdn.net/cnh294141800/article/details/53768464

Paxos算法是分布式中一個著名的一致性算法。它的假設(shè)前提是,在分布式系統(tǒng)中進(jìn)程之間的通信會出現(xiàn)丟失、延遲、重復(fù)等現(xiàn)象,但不會出現(xiàn)傳錯的現(xiàn)象。Paxos算法就是為了保證在這樣的系統(tǒng)中進(jìn)程間基于消息傳遞就某個值達(dá)成一致。要理解paxos算法最好還是看作者本人(Leslie Lamport)的論文《The Part-Time Parliament》。在這里只是簡單地介紹paxos最核心的思想,其實(shí)它還有很多的內(nèi)容。

Paxos算法的目的

Paxos算法的目的是為了解決分布式環(huán)境下一致性的問題。
多個節(jié)點(diǎn)并發(fā)操縱數(shù)據(jù),如何保證在讀寫過程中數(shù)據(jù)的一致性,并且解決方案要能適應(yīng)分布式環(huán)境下的不可靠性(系統(tǒng)如何就一個值達(dá)到統(tǒng)一)

Paxos的兩個組件

提議者和決議者是這里最重要的兩個角色,paxos最核心的算法就是定義他們之間的通訊規(guī)則來保證某個變量在分布式系統(tǒng)中的一致性。

Proposer

提議發(fā)起者,處理客戶端請求,將客戶端的請求發(fā)送到集群中,以便決定這個值是否可以被批準(zhǔn)。

Acceptor

提議批準(zhǔn)者,負(fù)責(zé)處理接收到的提議,他們的回復(fù)就是一次投票。會存儲一些狀態(tài)來決定是否接收一個值

Paxos有兩個原則

  1. 安全原則---保證不能做錯的事
    a) 針對某個實(shí)例的表決只能有一個值被批準(zhǔn),不能出現(xiàn)一個被批準(zhǔn)的值被另一個值覆蓋的情況;(假設(shè)有一個值被多數(shù)Acceptor批準(zhǔn)了,那么這個值就只能被學(xué)習(xí))
    b) 每個節(jié)點(diǎn)只能學(xué)習(xí)到已經(jīng)被批準(zhǔn)的值,不能學(xué)習(xí)沒有被批準(zhǔn)的值。
  2. 存活原則---只要有多數(shù)服務(wù)器存活并且彼此間可以通信,最終都要做到的下列事情:
    a) 最終會批準(zhǔn)某個被提議的值;
    b) 一個值被批準(zhǔn)了,其他服務(wù)器最終會學(xué)習(xí)到這個值。

Paxos的兩個階段

第一階段(prepare)

  1. 獲取一個proposal number, n;
  2. 提議者向所有節(jié)點(diǎn)廣播prepare(n)請求;
  3. 接收者(Acceptors比較善變,如果還沒最終認(rèn)可一個值,它就會不斷認(rèn)同提案號最大的那個方案)比較n和minProposal,如果n>minProposal,表示有更新的提議minProposal=n;如果此時該接受者并沒有認(rèn)可一個最終值,那么認(rèn)可這個提案,返回OK。如果此時已經(jīng)有一個accptedValue, 將返回(acceptedProposal,acceptedValue);
  4. 提議者接收到過半數(shù)請求后,如果發(fā)現(xiàn)有acceptedValue返回,表示有認(rèn)可的提議,保存最高acceptedProposal編號的acceptedValue到本地

第二階段(Accept)

  1. 廣播accept(n,value)到所有節(jié)點(diǎn);
  2. 接收者比較n和minProposal,如果n>=minProposal,則acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;
    否則,拒絕并且返回minProposal
  3. 提議者接收到過半數(shù)請求后,如果發(fā)現(xiàn)有返回值>n,表示有更新的提議,跳轉(zhuǎn)1(重新發(fā)起提議);否則value達(dá)成一致。

提議者是提出議案的人。每個議案都有一個議案號,議案號是區(qū)別不同議案的唯一標(biāo)識,而且議案號是有大小次序的。這里的提議者不像我們真實(shí)世界里的提議者,這里的提議者提的議案內(nèi)容不能隨心所欲。提議者和決議者要遵循下面的規(guī)則:

1) 提議者先給議案決定一個議案號,注意整個系統(tǒng)中議案號都不能重復(fù)的。然后發(fā)消息給所有決議者,告訴他們我要提出第幾號議案。

第一階段,提議者甲向決議者A、B、C、D、E、F、G發(fā)出議案號16的消息。

2) 決議者收到提議者發(fā)來的議案號后先看這個議案號是否是自己收到的所有議案號中最大的。如果不是,就不予理會;如果是,就把自己最后一次投票的議案發(fā)回去,如果沒投過議案就回復(fù)沒投過議案。

第二階段,決議者收到甲發(fā)來的議案號16后根據(jù)自己的情況作出回復(fù)

A、D未投過任何議案所以回復(fù)(null)

B最后一次投了2號議案所以回復(fù)(2,α)

C、F最后一次投了5號議案所以回復(fù)(5,β)

E的最大議案號是21所以不用回復(fù)

G由于網(wǎng)絡(luò)原因沒收到消息

3) 當(dāng)提議者收到過半回復(fù)后才能決定議案的內(nèi)容。在所有回復(fù)中議案號最大的那個議案的內(nèi)容就定為當(dāng)前議案的內(nèi)容。如果都回復(fù)沒投過議案,那議案內(nèi)容就由自己定了。如果只收到不過半數(shù)的回復(fù),那么這個過程就這樣結(jié)束了。確定議案內(nèi)容后就要把議案發(fā)給所有決議者。到此提議者的工作就可以結(jié)束了。

第三階段,甲根據(jù)回復(fù)確定16號議案的內(nèi)容,然后正式提出16號議案。

甲收到過半數(shù)人的回復(fù),回復(fù)的內(nèi)容有(null)、(2,α)、(5,β),其中5是最大的議案號,所以16號議案的內(nèi)容就定為β,接著甲就把(16,β)發(fā)出去。

4) 決議者收到議案后,就要對它進(jìn)行投票。如果這個議案號是自己收到的所以議案號中最大的,就要投這個議案的票;否則就不予理會。這里的投票沒有反對或贊成的類型之分。也就是可以認(rèn)為只有贊成票。到此決議者的工作就可以結(jié)束了。

第四階段,決議者收到16號議案并對它投票。

A、B、C、G收到(16,β)后,由于16號是他們的最大號,所以會給這個議案投票

D、E、F收到(16,β)后,由于21號是他們的最大號,所以不投票。

這個算法保證了某個變量在分布式系統(tǒng)中要么沒有值,要么就只會有一個值。只要某個議案在某一刻有過半數(shù)的人投票,那么這個值就永遠(yuǎn)定下來了。

如上圖,15號議案(內(nèi)容是β)有了過半數(shù)的投票,那么它的下一號16號議案內(nèi)容只能是β了,因?yàn)樵诘谌A段收到的回復(fù)如果過半數(shù),那么其中一定有(15,β),而15肯定是回復(fù)中最大的號,所以內(nèi)容只能是β。而下下一號21號議案內(nèi)容也只能是β,因?yàn)樗那皟蓚€議案的內(nèi)容都是β,如果收到的回復(fù)過半數(shù)的話肯定包含(15,β)或(16,β),而他們都是最大的兩個,所以內(nèi)容也只能是β了。可以證明其后的所有議案內(nèi)容都是β。雖然paxos算法可以保證不會有兩個值,但顯然不能保證一定會有值。這也是理論上(CAP理論)不能解決的問題

這里的算法是有改動的,提議者和決議者都還有后續(xù)的處理,而且關(guān)于上面的“過半數(shù)的決議者”也并不是Paxos本身的描述。Paxos本身定義的是一個更一般的“大多數(shù)”集合,每個議案都有一個“大多數(shù)”的決議者集合S,這些集合是兩兩相交的,對于每個議案,在第三階段要收到S中所有決議者的回復(fù)才能繼續(xù)下去。如果某個議案得到相應(yīng)S的全體投票,那么這個值就這么定下來了。


我們再來看一個例子

假設(shè)的3軍問題

  1. 1支紅軍在山谷里扎營,在周圍的山坡上駐扎著3支藍(lán)軍;
  2. 紅軍比任意1支藍(lán)軍都要強(qiáng)大;如果1支藍(lán)軍單獨(dú)作戰(zhàn),紅軍勝;如果2支或以上藍(lán)軍同時進(jìn)攻,藍(lán)軍勝;
  3. 三支藍(lán)軍需要同步他們的進(jìn)攻時間;但他們惟一的通信媒介是派通信兵步行進(jìn)入山谷,在那里他們可能被俘虜,從而將信息丟失;或者為了避免被俘虜,可能在山谷停留很長時間;
  4. 每支軍隊(duì)有1個參謀負(fù)責(zé)提議進(jìn)攻時間;每支軍隊(duì)也有1個將軍批準(zhǔn)參謀提出的進(jìn)攻時間;很明顯,1個參謀提出的進(jìn)攻時間需要獲得至少2個將軍的批準(zhǔn)才有意義;
  5. 問題:是否存在一個協(xié)議,能夠使得藍(lán)軍同步他們的進(jìn)攻時間?

接下來以兩個假設(shè)的場景來演繹BasicPaxos;參謀和將軍需要遵循一些基本的規(guī)則

  1. 參謀以兩階段提交(prepare/commit)的方式來發(fā)起提議,在prepare階段需要給出一個編號;
  2. 在prepare階段產(chǎn)生沖突,將軍以編號大小來裁決,編號大的參謀勝出;
  3. 參謀在prepare階段如果收到了將軍返回的已接受進(jìn)攻時間,在commit階段必須使用這個返回的進(jìn)攻時間;

兩個參謀先后提議的場景

  1. 參謀1發(fā)起提議,派通信兵帶信給3個將軍,內(nèi)容為(編號1);
  2. 3個將軍收到參謀1的提議,由于之前還沒有保存任何編號,因此把(編號1)保存下來,避免遺忘;同時讓通信兵帶信回去,內(nèi)容為(ok);
  3. 參謀1收到至少2個將軍的回復(fù),再次派通信兵帶信給3個將軍,內(nèi)容為(編號1,進(jìn)攻時間1);
  4. 3個將軍收到參謀1的時間,把(編號1,進(jìn)攻時間1)保存下來,避免遺忘;同時讓通信兵帶信回去,內(nèi)容為(Accepted);
  5. 參謀1收到至少2個將軍的(Accepted)內(nèi)容,確認(rèn)進(jìn)攻時間已經(jīng)被大家接收;
  6. 參謀2發(fā)起提議,派通信兵帶信給3個將軍,內(nèi)容為(編號2);
  7. 3個將軍收到參謀2的提議,由于(編號2)比(編號1)大,因此把(編號2)保存下來,避免遺忘;又由于之前已經(jīng)接受參謀1的提議,因此讓通信兵帶信回去,內(nèi)容為(編號1,進(jìn)攻時間1);
  8. 參謀2收到至少2個將軍的回復(fù),由于回復(fù)中帶來了已接受的參謀1的提議內(nèi)容,參謀2因此不再提出新的進(jìn)攻時間,接受參謀1提出的時間;

兩個參謀交叉提議的場景

  1. 參謀1發(fā)起提議,派通信兵帶信給3個將軍,內(nèi)容為(編號1);
  2. 3個將軍的情況如下
    a) 將軍1和將軍2收到參謀1的提議,將軍1和將軍2把(編號1)記錄下來,如果有其他參謀提出更小的編號,將被拒絕;同時讓通信兵帶信回去,內(nèi)容為(ok);
    b) 負(fù)責(zé)通知將軍3的通信兵被抓,因此將軍3沒收到參謀1的提議;
  3. 參謀2在同一時間也發(fā)起了提議,派通信兵帶信給3個將軍,內(nèi)容為(編號2);
  4. 3個將軍的情況如下
    a) 將軍2和將軍3收到參謀2的提議,將軍2和將軍3把(編號2)記錄下來,如果有其他參謀提出更小的編號,將被拒絕;同時讓通信兵帶信回去,內(nèi)容為(ok);
    b) 負(fù)責(zé)通知將軍1的通信兵被抓,因此將軍1沒收到參謀2的提議;
  5. 參謀1收到至少2個將軍的回復(fù),再次派通信兵帶信給有答復(fù)的2個將軍,內(nèi)容為(編號1,進(jìn)攻時間1);
  6. 2個將軍的情況如下
    a) 將軍1收到了(編號1,進(jìn)攻時間1),和自己保存的編號相同,因此把(編號1,進(jìn)攻時間1)保存下來;同時讓通信兵帶信回去,內(nèi)容為(Accepted);
    b) 將軍2收到了(編號1,進(jìn)攻時間1),由于(編號1)小于已經(jīng)保存的(編號2),因此讓通信兵帶信回去,內(nèi)容為(Rejected,編號2);
  7. 參謀2收到至少2個將軍的回復(fù),再次派通信兵帶信給有答復(fù)的2個將軍,內(nèi)容為(編號2,進(jìn)攻時間2);
  8. 將軍2和將軍3收到了(編號2,進(jìn)攻時間2),和自己保存的編號相同,因此把(編號2,進(jìn)攻時間2)保存下來,同時讓通信兵帶信回去,內(nèi)容為(Accepted);
  9. 參謀2收到至少2個將軍的(Accepted)內(nèi)容,確認(rèn)進(jìn)攻時間已經(jīng)被多數(shù)派接受;
  10. 參謀1只收到了1個將軍的(Accepted)內(nèi)容,同時收到一個(Rejected,編號2);參謀1重新發(fā)起提議,派通信兵帶信給3個將軍,內(nèi)容為(編號3);
  11. 3個將軍的情況如下
    a) 將軍1收到參謀1的提議,由于(編號3)大于之前保存的(編號1),因此把(編號3)保存下來;由于將軍1已經(jīng)接受參謀1前一次的提議,因此讓通信兵帶信回去,內(nèi)容為(編號1,進(jìn)攻時間1);
    b) 將軍2收到參謀1的提議,由于(編號3)大于之前保存的(編號2),因此把(編號3)保存下來;由于將軍2已經(jīng)接受參謀2的提議,因此讓通信兵帶信回去,內(nèi)容為(編號2,進(jìn)攻時間2);
    c) 負(fù)責(zé)通知將軍3的通信兵被抓,因此將軍3沒收到參謀1的提議;
  12. 參謀1收到了至少2個將軍的回復(fù),比較兩個回復(fù)的編號大小,選擇大編號對應(yīng)的進(jìn)攻時間作為最新的提議;參謀1再次派通信兵帶信給有答復(fù)的2個將軍,內(nèi)容為(編號3,進(jìn)攻時間2);
  13. 將軍1和將軍2收到了(編號3,進(jìn)攻時間2),和自己保存的編號相同,因此保存(編號3,進(jìn)攻時間2),同時讓通信兵帶信回去,內(nèi)容為(Accepted);
  14. 參謀1收到了至少2個將軍的(accepted)內(nèi)容,確認(rèn)進(jìn)攻時間已經(jīng)被多數(shù)派接受;

基本思想

Paxos主要用于保證分布式存儲中副本(或者狀態(tài))的一致性。副本要保持一致,那么,所有副本的更新序列就要保持一致。因?yàn)閿?shù)據(jù)的增刪改查操作一般都存在多個客戶端并發(fā)操作,到底哪個客戶端先做,哪個客戶端后做,這就是更新順序。如果不是分布式,那么可以利用加鎖的方法,誰先申請到鎖,誰就先操作。但是在分布式條件下,存在多個副本,如果依賴申請鎖+副本同步更新完畢再釋放鎖,那么需要有分配鎖的這么一個節(jié)點(diǎn)(如果是多個鎖分配節(jié)點(diǎn),那么又出現(xiàn)分布式鎖管理的需求,把鎖給哪一個客戶端又成為一個難點(diǎn)),這個節(jié)點(diǎn)又成為單點(diǎn),豈不是可靠性不行了,失去了分布式多副本的意義,同時性能也很差,另外,還會出現(xiàn)死鎖等情況。

所以,說來說去,只有解決分布式條件下的一致性問題,似乎才能解決本質(zhì)問題。

Paxos解決這一問題利用的是選舉,少數(shù)服從多數(shù)的思想,只要2N+1個節(jié)點(diǎn)中,有N個以上同意了某個決定,則認(rèn)為系統(tǒng)達(dá)到了一致,并且按照Paxos原則,最終理論上也達(dá)到了一致,不會再改變。這樣的話,客戶端不必與所有服務(wù)器通信,選擇與大部分通信即可;也無需服務(wù)器都全部處于工作狀態(tài),有一些服務(wù)器掛掉,只有保證半數(shù)以上存活著,整個過程也能持續(xù)下去,容錯性相當(dāng)好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 分布式一致性算法——Paxos Paxos分析 Paxos算法是萊斯利·蘭伯特(Leslie Lamport)19...
    Bobby0322閱讀 1,009評論 0 3
  • 【這篇論文我翻一下來,首先感覺還是不好懂,很多地方結(jié)論的得出不夠清楚,需要讀者自己思考其中的原因。要理解Paxos...
    數(shù)碼資訊站閱讀 6,650評論 3 51
  • Paxos是什么 Paxos算法是基于消息傳遞且具有高度容錯特性的一致性算法,是目前公認(rèn)的解決分布式一致性問題最有...
    jiangmo閱讀 1,550評論 0 6
  • 持續(xù)更新 如何淺顯易懂地解說 Paxos 的算法? 參考資料 #8:知行學(xué)社的分布式系統(tǒng)與Paxos算法視頻課程,...
    xiewen閱讀 16,807評論 0 44
  • 親愛的雨萱: 昨晚我看到你笑靨如花,看到你內(nèi)心綻放!作為老師,這一刻,我是如此地開心,如此地滿足! 看到你從眉心微...
    常拓閱讀 502評論 0 8