【轉】Paxos算法2-算法過程

——轉自:{老碼農的專欄html

1.編號處理算法

  根據P2c ,proposer在提案前會先諮詢acceptor查看其批准的最大的編號和value,再決定提交哪一個value。以前咱們一直強調更高編號的proposal,而沒有說明低編號的proposal該怎麼處理。promise

|--------低編號(L<N)--------|--------當前編號(N)--------|--------高編號(H>N)--------|網絡

  P2c 的正確性是由當前編號N而產生了一些更高編號H來保證的,更低編號L在以前某個時刻,可能也是符合P2c 的,但由於網絡通訊的不可靠,致使L被延遲到與H同時提交,L與H有可能有不一樣的value,這顯然違背了P2c ,解決辦法是acceptor不接受任何編號已過時的proposal,更精確的描述爲:分佈式

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接收到的第一個proposal符合這個條件,也就是說P1a 蘊含了P1。性能

  關於編號問題進一步的討論請參考下節的【再論編號問題:惟一編號 】。學習

 

2. Paxos算法造成優化

  從新整理P2c 和P1a 能夠提出Paxos算法,算法分2個階段:spa

Phase1:prepare.net

  1. proposer選擇一個proposal編號n,發送給acceptor中的一個多數派
  2. 若是acceptor發現n是它已回覆的請求中編號最大的,它會回覆它已accept的最大的proposal和對應的value(若是有);同時還附有一種承諾:不會批准編號小於n的proposal

Phase2:accept

  1. 若是proposer接收到了多數派的迴應,它發送一個accept消息到(編號爲n,value v的proposal)到acceptor的多數派(能夠與prepare的多數派不一樣),關鍵是這個value v是什麼,若是acceptor迴應中包含了value,則取其編號最大的那個,做爲v;若是迴應中不包含任何value,則有proposer隨意選擇一個
  2. acceptor接收到accept消息後check,若是沒有比n大的迴應比n大的proposal,則accept對應的value;不然拒絕或不迴應

  感受算法過程異常地簡單,而理解算法是怎麼造成卻很是困難。再仔細考慮下,這個算法又會產生更多的疑問:

 

再論編號問題:惟一編號


  保證paxos正確運行的一個重要因素就是proposal編號,編號之間要能比較大小/前後,若是是一個proposer很容易作到,若是是多個proposer同時提案,該如何處理?Lamport不關心這個問題,只是要求編號必須是全序的,但咱們必須關心。這個問題看似簡單,實際還稍微有點棘手,由於這本質上是也是一個分佈式的問題。

  在Google的Chubby論文中給出了這樣一種方法:

  • 假設有n個proposer,每一個編號爲ir (0<=ir <n),proposol編號的任何值s都應該大於它已知的最大值,而且知足:s %n = ir => s = m*n + ir
  • proposer已知的最大值來自兩部分:proposer本身對編號自增後的值和接收到acceptor的reject後所獲得的值
  • 以3個proposer P一、P二、P3爲例,開始m=0,編號分別爲0,1,2
  • P1提交的時候發現了P2已經提交,P2編號爲1 > P1的0,所以P1從新計算編號:new P1 = 1*3+0 = 4
  • P3以編號2提交,發現小於P1的4,所以P3從新編號:new P3 = 1*3+2 = 5

  整個paxos算法基本上就是圍繞着proposal編號在進行:proposer忙於選擇更大的編號提交proposal,acceptor則比較提交的proposal的編號是否已經是最大,只要編號肯定了,所對應的value也就肯定了。因此說,在paxos算法中沒有什麼比proposal的編號更重要。

 

活鎖


  當一proposer提交的poposal被拒絕時,多是由於acceptor promise了更大編號的proposal,所以proposer提升編號繼續提交。 若是2個proposer都發現本身的編號太低轉而提出更高編號的proposal,會致使死循環,也稱爲活鎖。

 

Leader選舉


   活鎖的問題在理論上的確存在,Lamport給出的解決辦法是選舉出一個proposer做leader,全部的proposal都經過leader來提交,當Leader宕機時立刻再選舉其餘的Leader。

  Leader之因此能解決這個問題,是由於其能夠控制提交的進度,好比果以前的proposal沒有結果,以後的proposal就等一等,不着急提升編號再次提交,至關於把一個分佈式問題轉化爲一個單點問題,而單點的健壯性是靠選舉機制保證。

問題貌似愈來愈複雜,由於又須要一個Leader選舉算法,但Lamport在fast paxos中認爲該問題比較簡單,由於Leader選舉失敗不會對系統形成什麼影響,所以這個問題他不想討論。可是後來他又說,Fischer, Lynch, and Patterson的研究結果代表一個可靠的選舉算法必須使用隨機或超時(租賃)。

  Paxos原本就是選舉算法,可否用paxos來選舉Leader呢?選舉Leader是選舉proposal的一部分,在選舉leader時再用paxos是否是已經在遞歸使用paxos?存在稱之爲PaxosLease的paxos算法簡化版能夠完成leader的選舉,像Keyspace、Libpaxos、Zookeeper、goole chubby等實現中都採用了該算法。關於PaxosLease,以後咱們將會詳細討論。

  雖然Lamport提到了隨機和超時機制,但我我的認爲更健壯和優雅的作法仍是PaxosLease。

 

Leader帶來的困惑


  Leader解決了活鎖問題,但引入了一個疑問:

  既然有了Leader,那隻要在Leader上設置一個Queue,全部的proposal即可以被全局編號,除了Leader是能夠選舉的,與Paxos算法1提到的單點MQ很是類似。

  那是否是說,只要從多個MQ中選舉出一個做爲Master就等於實現了paxos算法?如今的MQ自己就支持Master-Master模式,難道饒了一圈,paxos就是雙Master模式?

  僅從編號來看,的確如此,只要選舉出單個Master接收全部proposal,編號問題迎刃而解,實在無須再走acceptor的流程。但paxos算法要求不管發生什麼錯誤,都能保證在每次選舉中能選定一個value,並能被learn學習。好比leader、acceptor,learn均可能宕機,以後,還可能「甦醒」,這些過程都要保證算法的正確性。

  若是僅有一個Master,宕機時選舉的結果根本就沒法被learn學習, 也就是說,Leader選舉機制更多的是保證異常狀況下算法的正確性,虛驚一場,paxos原來不是Master-Master。

  在此,咱們第一次提到了"learn"這個角色,在value被選擇後,learn的工做就是去學習最終決議,學習也是算法的一部分,一樣要在任何狀況下保證正確性,後續的主要工做將圍繞「learn」展開。

 

Paxos與二段提交


Google的人曾說,其餘分佈式算法都是paxos的簡化形式。假如leader只提交一個proposal給acceptor的簡單狀況:

  • 發送prepared給多數派acceptor
  • 接收多數派的響應
  • 發送accept給多數派使其批准對應的value

其實就是一個二段提交問題,整個paxos算法能夠看做是多個交叉執行而又相互影響的二段提交算法。

 

如何選出多個Value


  Paxos算法描述的過程是發生在「一次選舉」的過程當中,這個在前面也提到過,實際Paxos算法執行是一輪接一輪,每輪還有個專有稱呼:instance(翻譯成中文有點怪),每instance都選出一個惟一的value。

  在每instanc中,一個proposal可能會被提交屢次才能得到acceptor的批准,通常作法是,若是acceptor沒有接受,那proposer就提升編號繼續提交。若是acceptor尚未選擇(多數派批准)一個value,proposer能夠任意提交value,不然就必須提交意見選擇的,這個在P2c 中已經說明過。

  Paxos中還有一個要提一下的問題是,在prepare階段提交的是proposal的編號,以後再決定提交哪一個value,就是value與編號是分開提交的,這與咱們的思惟有點不同。

 

3. 學習決議

  在決議被最終選出後,最重要的事情就是讓learn學習決議,學習決議就是決定如何處理決議。

  在學習的過程當中,遇到的第一個問題就是learn如何知道決議已被選出,簡單的作法就是每一個批准proposal的acceptor都告訴每一個須要學習的learn,但這樣的通訊量很是大。簡單的優化方式就是隻告訴一個learn,讓這個惟一learn通知其餘learn,這樣作的好是減小了通訊量,但壞處一樣明顯,會造成單點;固然折中方案是告訴一小部分learn,複雜性是learn之間又會有分佈式的問題。

  不管如何,有一點是確定的,就是每一個acceptor都要向learn發送批准的消息,若是不是這樣的話,learn就沒法知道這個value是不是最終決議,所以優化的問題縮減爲一個仍是多個learn的問題。

  可否像proposer的Leader同樣爲learn也選個Leader?由於每一個acceptor都有持久存儲,這樣作是能夠的,但會把系統搞的愈來愈複雜,以後咱們還會詳細討論這個問題。

  Learn學習決議時,還有一個重要的問題就是要按順序學習,以前的選舉算法花費不少精力就是爲了給全部的proposal全局編號,目的是能被按順序使用。但learn收到的決議的順序可能不不一致,有可能先收到10號決議,但9號還未到,這時必須等9號到達,或主動向acceptor去請求9號決議,以後才能學習9號、10號決議。

 

4. 異常狀況、持久存儲

  在算法執行的過程當中會產生不少的異常狀況,好比proposer宕機、acceptor在接收proposal後宕機,proposer接收消息後宕機,acceptor在accept後宕機,learn宕機等,甚至還有存儲失敗等諸多錯誤。

  但不管何種錯誤必須保證paxos算法的正確性,這就須要proposer、aceptor、learn都作能持久存儲,以作到server」醒來「後仍能正確參與paxos處理。

  • propose該存儲已提交的最大proposal編號、決議編號(instance id)
  • acceptor儲已promise的最大編號;已accept的最大編號和value、決議編號
  • learn存儲已學習過的決議和編號

  以上就是paxos算法的大概介紹,目的是對paxos算法有粗略瞭解,知道算法解決什麼問題、算法的角色及怎麼產生的,還有就是算法執行的過程、核心所在及對容錯處理的要求。

但僅根據上面的描述還很難翻譯成一個可執行的算法程序,由於還有無限多的問題須要解決:

  • Leader選舉算法
  • Leader宕機,但新的Leader還未選出,對系統會有什麼影響
  • 更多交叉在一塊兒的錯誤發生,還可否保證算法的正確性
  • learn到達該怎麼學習決議
  • instance no、proposal no是該維護在哪裏?
  • 性能

  衆多問題如雪片般飛來,待這些都逐一解決後才能討論實現的問題。固然還有一個最重要的問題,paxos算法被證實是正確的,但程序如何能被證實是正確的?

 

更多的請參考後面的章節。

相關文章
相關標籤/搜索