簡單理解Paxos演算法(譯)

大蟒傳奇發表於2019-03-04
簡單理解Paxos演算法(譯)

本文翻譯自Quora上的一個回答

我認為在瞭解Paxos前,可以先談談其他解決共識問題的方法,在這個基礎上再理解Paxos會簡單些。

結婚誓言是一種達成共識的直觀方式。

  • “你願意(若干省略)?”“我願意!”“我願意!”
  • “現在我宣佈你們(若干省略)”

兩階段提交

現在假設這場婚姻不是發生在兩個人之間,而是一個男人和多個女人之間。這個男人要麼娶所有人,要麼一個也不能娶。那麼,結婚誓言也要相應地改成下面的樣子:

  • “你願意(若干省略)?”“我願意!”“我願意!”“我願意!”……
  • “現在我宣佈你們(若干省略)”

如果其中一個女人沒有回應“我願意!”,那麼婚禮將無法進行。

電腦科學家稱之為兩階段提交。

兩階段提交(2PC)過程如下:

  1. 表決階段。一個協調者向所有節點釋出一個值並且收集它們的返回(接受或者不接受)。在我們的場景中,一個事務協調者詢問所有的資源管理器RM(資料庫伺服器例項)是否可以提交一個事務,RM回答是或者不是。
  2. 提交階段。如果所有人都同意,協調者將告訴所有節點這個值被確定下來了;如果有哪怕一個節點不同意,協調者將告訴所有節點這個值沒有被確定下來。在我們的場景中,協調者要求RM提交事務或者終止事務。

注意表決僅僅針對本次提出的值,節點可以回應是或者不是,而不能提出一個替代值。如果一個節點想要提出一個值,它應該開始自己的2PC。顯然,這個演算法是管用的,一個節點提出的值要由所有節點同意;同時,這個演算法的效率較低下,對於一個擁有N個節點的叢集,完成共識需要傳輸3N條資訊。

如果某個節點掛掉了呢?比如,在階段1中,協調者向部分節點(不是全部節點)傳送提議後掛掉。

  • 現在部分節點開始第二階段,而其他的節點還不知道。那些開始第二階段的節點將會阻塞。
  • 在我們的場景中,表決過的RM可能不得不鎖住一些資源,並且不能啟用超時機制,因為協調者可能會恢復,然後繼續第二階段。

在第二階段,如果協調者向部分節點傳送提交的訊息後掛掉,類似的問題一樣會存在。通過另外一個協調者在監測到timeout時接管可以解決部分問題;這個節點和其他的節點保持通訊來發現其他節點的表決(需要節點持久化表決結果)從而結束事務。但是這個流程也有可能發生失敗從而導致事務可能無法恢復。結語:在發生節點失敗的情況下2PC並不可靠。

三階段提交

2PC的關鍵問題在於,當協調者掛掉時,沒有其他的角色能夠完成協議。這可以通過新增一個額外的步驟來完成:

  1. 第一階段。和2PC一樣,協調者向所有節點提出一個值。
  2. 第二階段。如果在第一階段所有節點返回“是”,協調者傳送一個“準備提交”的資訊,讓節點執行可以撤銷但是無法回覆的操作。每個節點向協調者確認已經收到“準備提交”的資訊。
  3. 第三階段。和2PC的階段一樣,如果協調者接收到所有節點的確認,那麼向所有節點傳送第一步協調的值,讓節點提交。如果協調者沒有接到所有節點的確認,那麼協調者取消本次事物。

假如協調者在上面的任何一個步驟掛掉,其他的任意參與者都可以接管這個角色,查詢其他節點的狀態。

  • 如果有任意RM向新協調者報告沒有收到“準備提交”資訊,新的協調者會知道沒有節點提交了該事務。新的協調者可以取消這個事物或者重新執行一遍流程。
  • 如果已經提交了事務的RM掛掉,我們會知道其他的RM都已經收到並且確認了“準備提交”資訊,不然協調者不會進行到提交階段。所以協調者可以從最後得到階段開始。

從上面可以看出,3PC可以很好地處理節點失敗的情況。代價是多了一個步驟,導致了系統更高的延遲。

在發生網路分割槽的情況下,3PC也處理的不夠好。假設所有接收到“準備提交”的RM都在分割槽1,其他的RM在分割槽2。這個會導致每個分割槽都會選舉出各自的恢復節點,恢復節點要麼提交事務,要麼取消事務。萬一網路分割槽消失,系統就會處於不一致的狀態。

Paxos

首先問一個問題,有比3PC更好的演算法嗎?3PC面臨的唯一問題是網路分割槽,對吧?要想回答這個問題,讓我們假設網路分割槽是唯一的問題(實際並不是,後面會提到)。由網路分割槽導致的一致性問題值得解決嗎?

首先,隨著雲端計算的興起,為了服務的可擴充套件性,可能會將服務部署在不同的大陸上;這種情況下,的確需要一個容忍網路分割槽的演算法。

第二,網路分割槽並不是3PC面臨的唯一問題。處理節點臨時故障,最常見的情況是故障-恢復-繼續上次執行。這種fail-recover模式也可以用來描述一個非同步的網路模型,在這個模型中,無法規定節點用於響應訊息的時間上限,因為永遠不能假定一個節點已經掛了–它們可能會很慢,或者網路可能會很慢。不能對這個模型採用超時機制。

3PC能處理fail-stop,但不能處理fail-recover。不幸的是,現實情況需要處理fail-recover,因此,我們需要一個更通用的方案。Paxos就是這樣的方案。

工作過程

Paxos的工作過程和2PC很像:

  • 選擇一個節點成為leader/proposer。
  • leader選擇一個值,傳送到所有的節點(Paxos中稱之為acceptor),這個訊息被稱為“接受請求”訊息。acceptor可以回應接受或拒絕。
  • 一旦節點中的大多數回應接受,共識就能達成,協調者將“提交”訊息傳送到所有節點。

和2PC不同的關鍵在於,2PC需要所有節點同意,Paxos只需要大多數節點同意。這個想法很有意思,因為在兩個不同的大多數節點集合中,至少會有一個節點同時在這兩個集合中。這就可以保證,如果大多數節點都同意某個值,隨後任何想做出提議的節點都能從其他節點發現這個值並同意。這意味著,即使一半的急誒單無法回覆,Paxos演算法也能進行下去。

當然,leader本身可能也會掛掉。為此,Paxos不會在給定的時間點授予當個節點leader職責。演算法允許任意節點成為leader,並且協調事務。這自然意味著在給定的時間點,可能存在多個認為自己是leader的節點。在這種情況下,兩個leader也許會提出不同的值。那麼,如何在這種情況下達到共識呢?Paxos為此設計了兩種機制:

  • 為leader分配順序。這樣每個節點就能區分現有的leader和從失敗中恢復過來的leader,從而防止舊的leader阻礙共識的達成。
  • 對leader提出的值進行限制。一旦在某個值上達成了共識,Paxos強迫後面的leader也選擇這個值來保證共識的延續。讓acceptor傳送其最近確認的值和傳送該值leader的序列號,來實現這一點。新的leader可以選擇一個從acceptor接收的值;如果沒有值被髮送,leader可以選擇自己提出的值。

協議過程

準備階段

  • 一個節點選擇成為leader,選擇一個序列號x和值v來建立一個提議P1(x, v)。leader將這個提議傳送給acceptor,等待大多數節點的返回。
  • acceptor在收到提議P1(x, v)後,判斷:
    • 如果提議是該acceptor要接受的第一個提議,回覆“同意”,承諾leader該acceptor未來不會接受小於x的請求。
    • 如果該acceptor之前有接受過提議:
      • 比較x和之間和之前接受的最高序列號的提議,比如P2(y,v2)
      • 如果x<y,回覆拒絕和y值
      • 如果x>y,回覆同意和P2(y, v2)

接受階段

  • 如果大多數的acceptor回覆“拒絕”或者沒有回覆,leader取消本次提議。
  • 如果大多數的acceptor回覆“同意”,leader也能知道acceptor已經接受的提議。leader從這些值中任選一個值(如果沒有值被接受,選擇自己的值),傳送“接受請求”訊息,帶著提議的序列號和值(x, v)。
  • 當acceptor收到“接受請求”訊息,如果滿足下面的兩個條件,就傳送“接受”,否則返回“拒絕”。
    • v和之前接受的某個值相同
    • x是該acceptor所接受提議中序列號的最大值
  • 如果leader沒有從大多數節點中收到“接受”訊息,leader取消這次提議然後重新開始;如果leader從大多數節點中收到了“接受”訊息,本次協商就結束了。作為優化,leader可以傳送“提交”訊息給其他的節點。

Paxos失敗處理

在Paxos演算法中,如果我們指定叢集中同一時間只能有一個leader,並且要求所有節點都要投票呢?是的,我們就得到了2PC。2PC是Paxos的一個特例

如上所述,Paxos比2PC更能容忍失敗:

  • leader掛掉。其他的leader可以提出自己的提議來繼續協議。
  • 掛掉的leader恢復。由於節點只會同意具有最大序列值的提議,並且只提交之前接受的值,所以兩個節點能夠同時共存。

Paxos也比3PC更能容忍失敗,尤其是在網路分割槽的情況下。在3PC中,如果兩個分割槽分別同意一個值,那麼當分割槽消失時,系統會處於不一致的狀態。在Paxos中,這個問題不會存在,因為同意一個值需要大多數的節點參與。除非一個分割槽裡面的節點佔大多數,否則共識不能達成。如果佔有多數節點的分割槽達成共識,這個共識需要另外一個分割槽的節點接受。

Paxos可能出現的問題是,當兩個leader由於節點不能獲知彼此的存在時,不停地提出比原來提議序列號高的提議,這會導致Paxos不能終止。最終兩個leader獲知了彼此的存在,其中一個做出讓步。

這是一個一致性和實時性之間的妥協。Paxos保證了一致性,一旦共識達成,值就不會被修改。但是,Paxos不保證可用,在某些極端情況下可能無法達成共識。事實上,一個非同步演算法不能保證既安全又實時。這被稱之為FLP不可能結果

延伸閱讀


歡迎大家關注我的微信公眾號《派森公園》

簡單理解Paxos演算法(譯)

相關文章