分佈式一致性算法 Paxos

Paxos 是著名的分佈式一致性算法,Google Chubby的作者Mike Burrows對Paxos的評價極高:

“這個世界上只有一種一致性算法,那就是 Paxos”。

其實也不爲過,像非常有名的 Raft 算法、Zab 算法等都是基於 Paxos 的簡化和改進。

Paxos 解決什麼問題

Paxos 是解決分佈式環境下多節點的數據一致性問題,先看下一致性問題。

例如一個cache集羣有3個節點,每個節點都可以寫入。

集羣內各個節點需要做數據同步,如果沒有一致性算法做保證,3個節點內數據就可能混亂,例如:

節點1收到請求後,同步給節點2、3,節點2立即收到了,但因爲網絡原因,節點3沒有立即同步。

在節點3同步之前,節點2也發起了同步請求,因爲2、3間的網絡狀況好,節點3立即同步了。

所以,節點1、2的同步順序是 x=1,x=2,而節點3的同步順序是 x=2,x=1,造成了節點間數據不一致。

Paxos 就是用來解決這個問題,保證各節點數據的絕對一致,不會混亂。

Paxos 的基本思路

Paxos把每次對數據的更改稱爲一個提案,就像一個委員會,其中一人發起一個提案,委員會成員對這個提案投票,票數過半的通過。

有3個角色:

1.Proposer,提出提案2.Acceptor,對提案進行投票3.Learner,獲取投票結果

Proposer 和 Acceptor 是委員會的,Learner 不參與投票過程,只接受通過的提案,所以可先忽略這個角色。

一次Paxos算法的執行實例中,只批准一個value,過程分爲2個階段:

(1)Prepare 準備階段

Proposer 想發起提案,問各個 Acceptor :我是否可以發起?

(2)Accept 接受階段

如果多數 Acceptor 都同意,那麼 Proposer 就真正發出自己的提案,請求大家接受。 如果多數 Acceptor 都同意了,提案生效。

Acceptor 如何判斷是否同意提案呢?下面是整個流程。

首先需要知道,Acceptor 持有3個變量:

1.minProposal,自己目前持有的最小提案編號2.acceptedProposal,已經接受的提案編號3.acceptedValue,已經接受的提案內容

然後看流程圖:

對照上面那個示例,使用Paxos算法後,流程可能就是這樣的:

節點1收到 x=1 的請求,節點1成爲Proposer,拿到提案編號1,發起提案,得到了其他節點的同意,然後發送 accept(1,1)請求,請求大家接受。

節點1順利同意,但由於網絡問題,節點2、3暫時沒有收到,由於此提案沒有得到超過半數的同意,所以現在沒有生效。

這時節點2提出x=2的提案,順利得到大家的同意,因爲節點1已經接受了(1,1),會將其返回給節點2。

節點2收到大家的同意確認,發現節點1的返回信息中含有已經接受的提案,就將其提案內容作爲自己的提案,發送accept(2,1)

大家收到後,記錄提案內容,返回確認信息,節點2的提案生效了。

在此之後節點2、3才收accept(1,1)請求,由於這個請求的提案編號1小於自己已經接受的提案編號2,所以不會同意,直接拒絕。

最終,3個節點都是x=1,保持一致。

Paxos 的3中典型情況

爲了方便理解,下面以5個節點爲例。

1. 提案已經生效,後來的提案只能學習已生效的

節點1發起提案,編號爲1,得到了3個節點的同意,提案生效。

緊接着,節點2發起提案,編號爲2,發給了節點3、4、5。

節點3發現編號2大於自己的編號1,那麼同意,並返回了自己已經接受的提案(1,x)

節點5從所有返回值中找到提案編號最大的值x,作爲自己的提案內容,發出 accept(2,x)請求。

節點3、4、5收到後,發現編號大於自己的,接受了提案。

結果是所有節點的數據一致爲x

2. 提案未生效,但已經被某節點接受,後來的提案只能學習已經接受的

節點1發起提案,因爲網絡問題,節點3最先接受,節點1、2沒有接受。

然後節點5發起提案,發給節點3、4、5。

節點3一看編號比自己的大,表示同意,同時返回自己已經接受的(1,x)

節點5收到回覆後,從所有返回值中找到編號最大的值x,作爲自己的提案內容,發起接受請求accept(2,x)

節點3、4、5接到後,記錄提案,提案生效。

同時,節點1、2也收到了節點1的accept請求,記錄提案。

結果是所有節點的數據一致爲x

3. 先發起的提案失效,後來的提案生效

節點1發起提案,節點1、2、3同意,但因爲網絡問題,節點1最先接受。

在節點2、3還未接受時,節點5發起提案,發給了3、4、5。

節點3、4、5一看編號比自己的大,同意。

此時,節點3收到了節點1的accept請求,因爲此時節點3自己記錄的編號是2,大於節點1的編號,所以,節點3決絕了節點1的accept請求。

節點5收到大家的確認後,從返回值中沒有找到已接受的提案,所以使用自己的提案內容y作爲提案內容,發起accept(2,y)請求。

節點3、4、5接受,提案y生效。

節點1的提案沒有得到多數同意,所以失效,節點1、2需要接受已經生效的提案。

小結

以上是Paxos最基本的思路,如果有興趣,可以好好看看這兩篇文章:

https://segmentfault.com/a/1190000018844326

https://zh.wikipedia.org/zh-cn/Paxos算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章