1. 程式人生 > >Paxos演算法-基於訊息傳遞的一致性演算法

Paxos演算法-基於訊息傳遞的一致性演算法

1.來源
Paxos演算法是萊斯利·蘭伯特(Leslie Lamport)於1990年提出的一種基於訊息傳遞的一致性演算法。

1.1.故事
在古希臘,有一個叫做Paxos的小島,島上通過議會的形式來通過法令,議會中議員通過信使來傳遞訊息。議員和信使都是兼職的,他們隨時有可能離開會議廳,並且信使可能會重複的傳遞訊息,也可能丟失訊息。因此議會要保證在這種情況下法令仍然能夠正確地產生,並且不會出現衝突。

1.2.波折
1990年,The Part-Time Parliament,完成並投稿,無人能懂,被拒
1996年,上述論文被重審,Nancy Lynch公佈修改版Revisiting the Paxos Algorithm
1998年,The Part-Time Parliament終於被ACM TOCS接收
2001年,Lamport本人重新講述原文,發表了論文Paxos Made Simple

2.分散式事務的CAP理論
一致性(Consistency)
可用性(Availability)
分割槽容錯性(Partition Tolerance)
三者不可兼得

3.常見一致性協議
兩階段提交
三階段提交
ZAB協議
Paxos協議
Raft協議
3.1.限定
只有被提出的提案才能被選定
在被提出的提案中,只有一個提案會被選定
如果沒有被提出,那麼就不會有被選定的提案
當一個提案被選定後,程序可以獲取被選定的提案資訊
任一程序認為被選定的那個提案,必須是真的被選定的那個

4.Paxos演算法
4.1.角色
Proposer(選舉中對某個職位提出候選人的倡議者)

傳送Prepare請求給Acceptor
傳送Accept請求給Acceptor
Acceptor(對倡議者提出的候選人進行投票的參與者)

接收Prepare請求,並回復Prepare請求
接收Accept請求,併發送Result給Learner
Learner(類似於沒有投票權的群眾)

接收Result
4.2.通訊方式
不同角色之間可以通過傳送訊息來進行通訊,那麼:每個角色以任意的速度執行,可能因出錯而停止,也可能會重啟
一個value被選定後,所有的角色可能失敗然後重啟,除非那些失敗後重啟的角色能記錄某些資訊,否則等他們重啟後無法確定被選定的值
訊息在傳遞過程中可能出現任意時長的延遲,可能會重複,也可能丟失。但是訊息不會被損壞,即訊息內容不會被篡改
4.3.推導
4.3.1.一個Acceptor
假設只有一個Acceptor(可以有多個Proposer),只要Acceptor接受它收到的第一個提案,則該提案被選定,該提案裡的value就是被選定的value。這樣就保證只有一個value會被選定。

缺陷:唯一的Acceptor宕機,就徹底崩潰了

4.3.2.多個Acceptor
4.3.2.1.約定

P1:一個Acceptor必須接受它收到的第一個提案
一個提案被選定需要被半數以上的Acceptor接受,那麼一個Acceptor必須能夠接受不止一個提案
P1a:一個Acceptor只要尚未響應過任何編號大於M的Prepare請求,那麼他就可以接受這個編號為M的提案
P2:如果某個value為v的提案被選定了,那麼每個編號更高的被選定提案的value必須也是v
P2a:如果某個value為v的提案被選定了,那麼每個編號更高的被Acceptor接受的提案的value必須也是v
P2b:如果某個value為v的提案被選定了,那麼之後任何Proposer提出的編號更高的提案的value必須也是v
P2c:對於任意的M和V,如果提案[M, V]被提出,那麼存在一個半數以上的Acceptor組成的集合S,滿足以下兩個條件中的任意一個:
S中每個Acceptor都沒有接受過提案
S中Acceptor接受過的最大編號的提案的value為V
4.3.2.2.推論
4.3.2.2.1.滿足P2b

Proposer生成提案之前,應該先去“學習”已經被選定或者可能被選定的value,然後以該value作為自己提出的提案的value。如果沒有value被選定,Proposer才可以自己決定value的值。這樣才能達成一致。這個學習的階段是通過一個“Prepare請求”實現的。

4.3.2.2.2.滿足P1a
如果Acceptor收到一個編號為M的Prepare請求,在此之前它已經響應過編號大於M的Prepare請求。該Acceptor不可能接受編號為M的提案。因此,該Acceptor可以忽略編號為M的Prepare請求。當然,也可以回覆一個error,讓Proposer儘早知道自己的提案不會被接受。

4.3.2.3.提案生成
Proposer選擇一個新的提案編號M,然後向某個Acceptor集合(半數以上)傳送Prepare請求,要求該集合中的每個Acceptor做出如下響應:
向Proposer承諾保證不再接受任何編號小於M的提案
如果Acceptor已經接受過提案,那麼就向Proposer響應已經接受過的編號小於M的最大編號的提案
如果Proposer收到了半數以上的Acceptor的響應,那麼它就可以生成編號為M,Value為V的提案[M,V]。其中V是所有的響應中編號最大的提案的Value。如果所有的響應中都沒有提案,那麼此時V就可以由Proposer自己選擇。
生成提案後,Proposer將該提案發送給半數以上的Acceptor集合,並期望這些Acceptor能接受該提案。稱該請求為Accept請求。
4.3.2.4.接收提案
Acceptor接收到Prepare請求編號M,
當前響應的最大編號>M,則忽略或回覆error
當前響應的最大編號<M,
當前已接受[N,B]的Accept請求,則回覆M,B
當前未接受,則記錄M,返回ACK
Acceptor接收到Accept請求[M,V]
當前響應的最大編號>M,則忽略或回覆error
當前響應的最大編號<M,
當前未接受,則記錄[M,V],並通知Learner,V
當前已接受[N,B]的Accept請求,則
N>M,則忽略或回覆error
N<M,則記錄[M,V],並通知Learner,V
4.3.2.5.流程
階段1
Proposer選擇一個提案編號M,然後向半數以上的Acceptor傳送編號為M的Prepare請求
如果一個Acceptor收到一個編號為M的Prepare請求,且M大於該Acceptor已經響應過的所有Prepare請求的編號,那麼它就會將它已經接受過的編號最大的提案(如果有的話)作為響應反饋給Proposer,同時該Acceptor承諾不再接受任何編號小於M的提案
階段2
如果Proposer收到半數以上Acceptor對其發出的編號為M的Prepare請求的響應,那麼它就會發送一個針對[M,V]提案的Accept請求給半數以上的Acceptor
如果Acceptor收到一個針對編號為M的提案的Accept請求,只要該Acceptor沒有對編號大於M的Prepare請求做出過響應,它就接受該提案,並通知Learner
階段3
Learner收到Acceptor對其傳送的結果V,如果收到半數以上,那麼認為V被選定;如果沒有收到半數以上