Paxos在分布式系統(tǒng)中的重要性無(wú)需多言。我們能在網(wǎng)絡(luò)上找到非常多解析Paxos原理的文章,這些文章大部分只講協(xié)議的過(guò)程,有些深入的文章還會(huì)講協(xié)議的證明,我總感覺缺少對(duì)Paxos協(xié)議“生動(dòng)直觀”的理解。最終我認(rèn)為最直觀解釋Paxos的文章是作者Lamport在2001年發(fā)表的《Paxos Made Simple》。作者寫這篇文檔的目的是因?yàn)?998年發(fā)表的paxos原文《The part-time parliament》被很多人吐槽晦澀難懂。在《Paxos Made Simple》文中作者對(duì)Paxos協(xié)議做了一次從簡(jiǎn)單場(chǎng)景到完整協(xié)議的推演。我寫這篇文章沒有什么新奇的地方,僅僅寫我對(duì)《Paxos Made Simple》的推演過(guò)程的消化理解。
Paxos協(xié)議要解決的問(wèn)題:
在一個(gè)不可靠的分布式環(huán)境中,各個(gè)實(shí)體達(dá)成一個(gè)一致的狀態(tài)。
如果系統(tǒng)中只有一個(gè)proposal,那么這個(gè)proposal的提議在大多數(shù)acceptor存活時(shí),必須要被接受。因此
P1.? An acceptor must accept the first proposal that it receives.
如果有多個(gè)proposal,每個(gè)acceptor只接受第一個(gè)proposal而拒絕后續(xù)所有的proposal的話。那么就可能會(huì)導(dǎo)致每個(gè)proposal都不能被大多數(shù)acceptor接受,導(dǎo)致協(xié)議無(wú)法收斂。因此:
每個(gè)acceptor接受的proposal不止一個(gè),當(dāng)然,只有被大多數(shù)acceptor接收的proposal才會(huì)被chosen
因此,我們?cè)试S多個(gè)proposal被選中,但是必須保證:這些被選中的proposal都有同樣的value。也就是說(shuō):
P2. If a proposal with value v is chosen, then every higher-numbered proposal that is chosen has value v.
如何來(lái)保證只要一個(gè)value為v的proposal被chosen,后續(xù)的proposal的值都為v呢?
P2a. If a proposal with value v is chosen, then every higher-numbered proposal accepted by any acceptor has value v.
簡(jiǎn)單啊,只要保證后面的被acceptor的proposal的值都為v就好了。那么如何保證后面的被accept的prososal都是v呢?
P2b. If a proposal with value v is chosen, then every higher-numbered proposal issued by any proposer has value v.
簡(jiǎn)單啊,只要后面proposer發(fā)出的proposal都為v就好了。(這不廢話嗎)
那么,如何保證一旦一個(gè)proposal被chosen,后續(xù)的proposal都跟之前的proposal有相同的value呢?
P2c. For any v and n, if a proposal with value v and number n is issued, then there is a set S consisting of a majority of acceptors such that either (a) no acceptor in S has accepted any proposal numbered less than n, or (b) v is the value of the highest-numbered proposal among all proposals numbered less than n accepted by the acceptors in S.
意思是我們要把好proposal的出口這一關(guān),就是說(shuō)proposal不能瞎jb提,這樣才能保證“達(dá)成一致”的這個(gè)過(guò)程最快速的收斂。P2c翻譯一下的意思就是:對(duì)于任何一個(gè)proposal(n,v)(n是提案編號(hào),v是提案值),如果要提出這個(gè)proposal,必須要滿足一下的兩個(gè)條件之一:
1.?大多數(shù)的acceptor都沒有accept小于n的proposal;?或者
2.?大多數(shù)的acceptor?accept的提案都小于n,這其中序號(hào)最大的一個(gè)提案的值就是v
怎么理解這兩個(gè)條件呢?直觀一點(diǎn)講就是,如果你想提案,要么1)大多數(shù)acceptor沒有接受過(guò)任何提案;要么2)你的提案跟之前最大編號(hào)的提案一樣。
好,其實(shí)paxos本質(zhì)上就是通過(guò)約束每個(gè)proposer要提出的proposal來(lái)達(dá)到快速達(dá)成一致的目的(收斂)。
那么如何來(lái)約束proposor提出的proposal呢?根據(jù)之前提出了兩個(gè)條件,因此proposer在提出proposal之前,必須先“學(xué)習(xí)”,學(xué)習(xí)當(dāng)前(大多數(shù)acceptor)最大提案的值。這個(gè)學(xué)習(xí)的過(guò)程叫做"Prepare":
Prepare階段
一個(gè)Proposer要想提案,它首先得知道當(dāng)前要么大部分acceptor沒有接受過(guò)任何提案,要么找到一個(gè)在大部分acceptor組成的集合中最大的提案值。因此Proposer首先獲取一個(gè)新的提案編號(hào),然后使用這個(gè)編號(hào)N向大部分acceptor發(fā)送prepare請(qǐng)求。這些acceptor給proposer響應(yīng)
1)要么大多數(shù)acceptor從來(lái)沒有接受過(guò)任何提案
2)要么有部分acceptor告訴proposer當(dāng)前最大的提案編號(hào)和提案值
? ? 2.1?有部分Acceptor的接受的最新的提案大于等于N,不可能。因?yàn)锳cceptor只返回小于N的最大編號(hào)和提案值。一個(gè)acceptor不會(huì)響應(yīng)一個(gè)小于它當(dāng)前提案編號(hào)的proposal。
? ? 2.2?所有的提案編號(hào)都小于N。
3)有返回的acceptor沒有達(dá)到大多數(shù)(proposal無(wú)法繼續(xù))
我們?cè)倏碅cceptor在Prepare階段的邏輯:
1)如果Acceptor沒有承諾/接受過(guò)任何提案,那么向Proposal直接返回承諾,也就是后續(xù)不會(huì)接收小于N的proposal
2)如果Acceptor?承諾過(guò)一個(gè)小于N的提案,那么Aceeptor可以直接向Proposal再次承諾N,也就是之前的小于N的Proposal將永遠(yuǎn)不會(huì)被自己Accept
3)如果Acceptor接受過(guò)一個(gè)小于N的提案,那么返回這個(gè)提案編號(hào)和提案值
4)如果Acceptor承諾過(guò)一個(gè)大于N的提案,那么忽略當(dāng)前為N的提案(承諾也沒用,因?yàn)榫退愠兄Z了N,也不可能接受N)
5)如果Acceptor接受過(guò)一個(gè)大于N的提案,那么忽略當(dāng)前為N的提案
一旦Acceptor給出了Prepare階段的響應(yīng),意味著這個(gè)Acceptor將不會(huì)接受小于N的提案。什么意思呢?只要一個(gè)Proposal通過(guò)了Prepare階段,也就意味著任何一個(gè)小于N的Proposal如果還沒有Prepare,他將不能通過(guò)Prepare階段,如果通過(guò)了Prepare,它也不會(huì)被大多數(shù)acceptor接受。相當(dāng)于對(duì)整個(gè)acceptor集群做了一個(gè)鎖定操作,即鎖定不會(huì)有一個(gè)小于N的proposal被chosen。
但是也會(huì)出現(xiàn)這個(gè)問(wèn)題,當(dāng)為N的proposal在通過(guò)prepare階段之后但是還沒有還沒有發(fā)送acceptor請(qǐng)求之前,另一個(gè)proposer發(fā)起了一個(gè)編號(hào)為N+1的proposal,這個(gè)時(shí)候N+1也可以通過(guò)Prepare階段,接著另一個(gè)Proposor可能再發(fā)起一個(gè)N+2的proposal,這樣整個(gè)協(xié)議過(guò)程將無(wú)法收斂。
Accept階段
Proposer在Acceptor階段的邏輯:當(dāng)?shù)谝浑A段學(xué)習(xí)(Prepare)完成后,Proposal收到了大部分Acceptor的響應(yīng)。
1. 如果有一個(gè)最大的Proposal被接受,也就以為著當(dāng)前沒有任何一個(gè)大于N的proposal被chosen。那么Proposer將會(huì)用自己選用的Proposal編號(hào)和學(xué)習(xí)到的當(dāng)前最大Proposal的值作為新提案發(fā)起Accept請(qǐng)求。 (是否意味著有可能已經(jīng)有小于N的proposal被chosen?有可能。是否意味著有可能有多個(gè)小于N的proposal被chosen?有可能。但是沒關(guān)系,因?yàn)檫@些已經(jīng)被chosen的提案值和當(dāng)前將要發(fā)出的提案值都一樣)。
2. 如果大部分的Acceptor沒有接受過(guò)任何Proposal,那么Proposer可以自己指定任何提案值發(fā)起Accept請(qǐng)求。
Acceptor在Accept階段的邏輯:
P1a. An acceptor can accept a proposal numbered n iff it has not responded to a prepare request having a number greater than n.
也就是,如果Acceptor沒有承諾過(guò)大于N的proposal,那它就可以accept?N。(如果他Accept過(guò)小于N的proposal呢?)。一個(gè)Acceptor需要記住兩樣?xùn)|西:
1.?已經(jīng)承諾過(guò)的最大提案編號(hào),用來(lái)忽略大于此編號(hào)的prepare和accept請(qǐng)求
2.?已經(jīng)接受過(guò)的最大提案編號(hào)和提案值,用來(lái)約束后續(xù)的提案值(通過(guò)后續(xù)提案的prepare請(qǐng)求)
到此為止,這個(gè)協(xié)議的邏輯算講完了。