basic paxos協議——分佈式一致性協議初探

1、什麼是paxos協議?

定義:Paxos算法是在多個成員之間對某個值(提議)達成一致的協議。這個值可以是任何東西。比如多個成員之間進行選主,那麼這個值就是主的身份。在應用到日誌同步中時,這個值就是一條日誌。通過多次Paxos的執行就可確定出一個日誌的序列,保證在主備服務器上看到相同的日誌順序。

前提:Paxos算法假設不存在拜占庭問題,也就是說消息的傳遞可能丟失,遲到或者重複,但是一定不會被篡改。

拓展:Paxos算法有很多變種,旨在提高共識收斂速度、減少通信延遲或減少磁盤IO次數,典型的包括Multi-PaxosFast PaxosGeneralized Paxos

思考:爲什麼需要paxos協議?爲什麼不直接統計投票,得票最多的值得選?

我們日常中最常見的表決方式就是投票,得到選票數最多的值爲決議結果,那麼爲什麼在分佈式系統中不使用這種簡單的方法呢,主要有兩個原因:

  • 一個是沒有組織者。也就是說沒有一個leader節點來發起投票,多個(甚至所有)的節點都覺得自己是leader節點,都要發起投票,那不是亂套了。
  • 二個是不知道投票選項。因爲節點間相互沒有通信,所以根本不知道有哪些選項,這樣是沒有辦法進行投票的(就像着急一羣不認識的人來選舉主席,但是大家相互不認識,也不告訴大家有哪些人蔘與選舉,總不能隨便寫個名字就交上去,因爲很可能亂寫的名字根本沒有這個人)。而paxos協議的準備階段解決了第二個問題。

2、Paxos算法流程

paxos協議的決議形成需要兩個階段:準備階段、決議階段

我們將使用一個具體的集羣選主的例子來描述paxos算法的流程:

(1)準備階段

發送proposal請求,不帶具體提案值。目的是收集其它節點的意見並得到自己的提案值,也就是確定本輪paxos算法要表決的提案。

  •   每個proposer發送的proposal消息包含自己的提案編號(唯一,隨時間遞增)
  •   接收的回覆消息包含自己已經參與表決的提案編號和提案值[round,value],如果之前沒有參與過,那麼返回[round,null]
  •   對於發起者proposer來說,如果收到的所有消息的value都爲null,那麼在接下來的決議階段提案值爲自己,否則提案值爲準備階段收到的消息中round最大的消息對應的value(即參考文獻中的maxVote值)

我們假設在一個分佈式集羣中有3個sever,我們需要在其中選一個作爲leader,因此3個server分別作爲proposer發出proposal請求:而3個server發起proposal的時間稍微存在差異,這裏proposer2最先(假設在3:01),proposer1其次(3:02),proposer3最後(3:03),我們根據發起時間給每個proposal請求分配提案號(round),可以得到proposer2的提案號爲1,proposer1的提案號爲2,proposer3的提案號爲3,如下圖所示,我們把proposal請求簡稱爲P1(P2,P3),這裏的proposal請求的內容包含的就是提案號(round),比如說“你好,我的提案號是1,請問你有什麼想法”。

如下圖所示,P1請求發送給accepter1、2(最先達到),P2請求發送給accepter2、3(其次到達),P3請求發送給accepter2、3(最後到達)。

那麼接下來我們對準備階段的流程進行模擬,最後可以得到各個proposer的最終提案值:

(2)決議階段

發送accept請求,攜帶具體的提案值。目的是告訴集羣自己的提案,並由決議算法得到最後的決議。在決議階段會繼續使用準備階段的accept的情況,並且一個節點始終都只能支持一個提案,因此,在決議階段一定會有且只有一個超過半數的提案被作爲決議,保證一致性。

  •   每個proposer發送自己的提案號和最終的提案值[round,value]給各個accepter
  •   每個accepter將收到的消息提案號與自己在準備階段的意向比較,如果收到的提案號大於之前的意向提案號,則接受提案,否則拒絕
  •   選擇支持數過半的提案作爲最後的決議

對準備階段得到的提案值進行決議流程的模擬,得到最終的決議值[4,S2]:

  1. Acceptor1、Acceptor2接收到Proposer1的提案[2,server1]請求,Acceptor2承諾編號大於4所以拒絕了通過,Acceptor1通過了請求;

  2. Proposer2的提案[4,server2]發送到了Acceptor2、Acceptor3,提案編號爲4所以Acceptor2、Acceptor3都通過了提案請求;

  3. Acceptor2、Acceptor3接收到Proposer3的提案[3,server3]請求,Acceptor2、Acceptor3承諾編號大於4所以拒絕了提案;

  4. 此時過半的Acceptor都接受了Proposer2的提案[4,server2],Larner感知到了提案的通過,Larner學習提案,server2成爲Leader;

發佈決議

而在決議形成後,要實現分佈式系統的最終一致性,還需要將決議分發布給分佈式系統中的learner節點,也就是說我們可以認爲一次分佈式系統的最終一致性結果可以分爲三個步驟:

  • 一個顯而易見的方法是當acceptors批准一個value時,將這個消息發送給所有learner。但是這個方法會導致消息量過大。
  • 由於假設沒有拜占庭問題,也就是消息不會被篡改,learners可以通過別的learners獲取已經通過的決議。因此acceptors只需將批准的消息發送給指定的某一個learner,其他learners向它詢問已經通過的決議。這個方法降低了消息量,但是指定learner失效將引起系統失效。
  • 因此acceptors需要將accept消息發送給learners的一個子集,然後由這些learners去通知所有learners。但是由於消息傳遞的不確定性,可能會沒有任何learner獲得了決議批准的消息。當learners需要了解決議通過情況時,可以讓一個proposer重新進行一次提案。注意一個learner可能兼任proposer

經過以上步驟,就可以將一個值(決議)一致地放到分佈式系統的各個節點中。

 

參考文章:

paxos算法流程:https://blog.csdn.net/steven_change/article/details/79875227

https://segmentfault.com/a/1190000005717258#articleHeader7

maxVote值的選取:https://blog.csdn.net/feng12345zi/article/details/79653996

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