分佈式一致性算法之Paxos

2pc、3pc、paxos、raft都是解決分佈式系統中的一致性問題的。

一、兩個類型的一致性(操作原子性與副本一致性)

1.2pc、3pc協議用於保證屬於多個數據分片上的操作的原子性。這些數據分片可能分佈在不同的服務器上,2PC、3PC協議保證多臺服務器上的操作要麼全部成功,要麼全部失敗。

2.Paxos協議用於保證同一個數據分片的多個副本之間的數據一致性。當這些副本分佈到不同的數據中心時。Raft協議解決Paxos的實現難度
關於2PC 3PC:分佈式事務之2pc、3pc

關於:分佈式之flp、cap、base理論、一致性問題、共識算法 

二、Paxos

參考:分佈式系列文章——Paxos算法原理與推導

1.簡介:

 Paxos算法是萊斯利·蘭伯特(Leslie Lamport)1990年提出的一種基於消息傳遞的一致性算法,它曾就此發表了《The Part-Time Parliament》,《Paxos Made Simple》,由於採用故事的方式來解釋此算法,感覺還是很難理解。

 Paxos算法是目前公認的解決分佈式一致性問題最有效的算法之一,其解決的問題就是在分佈式系統中如何就某個值(決議)達成一致。比如master-slave模式下的選主。

在常見的分佈式系統中,總會發生諸如機器宕機或網絡異常(包括消息的延遲、丟失、重複、亂序,還有網絡分區)等情況。Paxos算法需要解決的問題就是如何在一個可能發生上述異常的分佈式系統中,快速且正確地在集羣內部對某個數據的值達成一致。即是分佈式系統中達成狀態的一致性。

這裏某個數據的值並不只是狹義上的某個數,它可以是一條日誌,也可以是一條命令(command)。。。根據應用場景不同,某個數據的值有不同的含義。

多個節點之間存在兩種通訊模型:

共享內存(Shared memory)

消息傳遞(Messages passing)

Paxos是基於消息傳遞的通訊模型的。

 故障(不響應)的情況稱爲“非拜占庭錯誤”惡意響應的情況稱爲“拜占庭錯誤”(對應節點爲拜占庭節點)

Paxos解決的是非拜占庭錯誤,即是Paxos的前提是假設信道是安全的,信號是不被篡改的。 

Paxos並沒有違背FLP不可能原理,Paxos放鬆了對liveness可終止性的要求,因此Paxos/Raft才能認爲是可行的, 嚴格講Paxos可能永遠無法結束

2.Paxos算法中的3種角色

Proposer 提案者

作用:負責提出提案Proposal

Proposer 在什麼情況下才能認爲某個value被選定呢?

只要Proposer發的提案被半數以上的Acceptor接受,Proposer就認爲該提案裏的value被選定了。

Acceptor 決策者

爲了避免單點故障,會有一個Acceptor集合,Proposer像Acceptor集合發送提案

作用:負責對提案作出裁決(accept與否)

Acceptor在什麼情況下才能認爲某個value被選定呢?

只要Acceptor接受了某個提案,Acceptor就任務該提案裏的value被選定了。

Learners 學習者

作用:負責學習提案結果

Learners在什麼情況下才能認爲某個value被選定呢?

Acceptor告訴Learner哪個value被選定,Learner就認爲那個value被選定。

3.對於一致性算法,安全性(safaty)要求如下:

  • 只有被提出的value才能被選定。
  • 只有一個value被選定,並且
  • 如果某個進程認爲某個value被選定了,那麼這個value必須是真的被選定的那個。

我們不去精確地定義其活性(liveness)要求。我們的目標是保證最終有一個提出的value被選定。當一個value被選定後,進程最終也能學習到這個value。

Paxos的目標:保證最終有一個value會被選定,當value被選定後,進程最終也能獲取到被選定的value。

三、Paxos算法描述

Paxos算法類似於兩階段提提交,其算法執行過程分爲兩個階段。具體如下:

階段一(prepare階段):

(a) Proposer選擇一個提案編號N,然後向半數以上的Acceptor發送編號爲N的Prepare請求。Pareper(N)

(b) Acceptor收到一個編號爲N的Prepare請求,

如果N小於它已經響應過的請求:

拒絕,不迴應或回覆error。

若N大於該Acceptor已經響應過的所有Prepare請求的編號(maxN):

那麼它就會將它已經接受過(已經經過第二階段accept的提案)的編號最大的提案(如果有的話,如果還沒有的accept提案的話返回{pok,null,null})作爲響應反饋給Proposer。

同時該Acceptor承諾不再接受任何編號小於N的提案。

階段二(accept階段):

(a) 如果一個Proposer收到半數以上Acceptor對其發出的編號爲N的Prepare請求的響應,那麼它就會發送一個針對[N,V]提案的Accept請求給半數以上的Acceptor。

注意:V就是收到的響應中編號最大的提案的value(某個acceptor響應的它已經通過的{acceptN,acceptV}),如果響應中不包含任何提案,那麼V就由Proposer自己決定

(b) 如果Acceptor收到一個針對編號爲N的提案的Accept請求,

只要該Acceptor沒有對編號大於N的Prepare請求做出過響應,它就接受該提案。

如果N小於Acceptor以及響應的prepare請求,則拒絕,不迴應或回覆error

(當proposer沒有收到過半的迴應,那麼他會重新進入第一階段,遞增提案號,重新提出prepare請求)。

流程圖:

 四、具體例子

問題背景:假設我們有下圖的系統,想要在server1,server2,server3選一個master。

1.prepare階段 

    (1)每個server向proposer發送消息,表示自己要當leader,

         假設proposer收到消息的時間不一樣,順序是: proposer2 -> proposer1 -> proposer3,消息編號依次爲1、2、3。 

         緊接着,proposer將消息發給acceptor中超過半數的子成員(這裏選擇兩個),

         如上圖所示,

         proposer2向acceptor2和acceptor3發送編號爲1的消息,

         proposer1向acceptor1和accepto2發送編號爲2的消息,

         proposer3向acceptor2和acceptor3發送編號爲3的消息。 

  (2)假設這時proposer1發送的消息先到達acceptor1和acceptor2,

          它們都沒有接收過請求,所以接收該請求並返回【pok,null,null】給proposer1,

          同時acceptor1和acceptor2承諾不再接受編號小於2的請求; 

         緊接着,proposer2的消息到達acceptor2和acceptor3,

          acceptor3沒有接受過請求,所以返回proposer2 【pok,null,null】,acceptor3並承諾不再接受編號小於1的消息。

          而acceptor2已經接受proposer1的請求並承諾不再接收編號小於2的請求,所以acceptor2拒絕proposer2的請求; 

          最後,proposer3的消息到達acceptor2和acceptor3,它們都接受過提議,但編號3的消息大於acceptor2已接受的2和acceptor3已接受的1,所以他們都接受該提議,並返回proposer3 【pok,null,null】; 

         此時,proposer2沒有收到過半的回覆,所以重新取得編號4,併發送給acceptor2和acceptor3,此時編號4大於它們已接受的提案編號3,所以接受該提案,並返回proposer2 【pok,null,null】。

2.accept階段 

(1)

       Proposer3收到半數以上(兩個)的回覆,並且返回的value爲null,所以,proposer3提交了【3,server3】的提案。 
  Proposer1也收到過半回覆,返回的value爲null,所以proposer1提交了【2,server1】的提案。 
  Proposer2也收到過半回覆,返回的value爲null,所以proposer2提交了【4,server2】的提案。 

   (這裏要注意,並不是所有的proposer都達到過半了才進行第二階段,這裏只是一種特殊情況)

(2) 
  Acceptor1和acceptor2接收到proposer1的提案【2,server1】,acceptor1通過該請求,acceptor2承諾不再接受編號小於4的提案,所以拒絕; 
  Acceptor2和acceptor3接收到proposer2的提案【4,server2】,都通過該提案; 
  Acceptor2和acceptor3接收到proposer3的提案【3,server3】,它們都承諾不再接受編號小於4的提案,所以都拒絕。

       所以proposer1和proposer3會再次進入第一階段,

      但這時候 Acceptor2和acceptor3已經通過了提案(AcceptN = 4,AcceptV=server2),並達成了多數,

     所以proposer會遞增提案編號,並最終改變其值爲server2。最後所有的proposer都肯定會達成一致,這就迅速的達成了一致。

  此時,過半的acceptor(acceptor2和acceptor3)都接受了提案【4,server2】,

    learner感知到提案的通過,learner開始學習提案,所以server2成爲最終的leader

五、Learner學習被選定的value

Learner學習(獲取)被選定的value有如下三種方案:

六、如何保證Paxos算法的活性

 通過選取主Proposer,就可以保證Paxos算法的活性。至此,我們得到一個既能保證安全性,又能保證活性分佈式一致性算法——Paxos算法

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