分散式理論(五) - 一致性演算法Paxos

零壹技術棧發表於2018-06-17

前言

世界上只有一種一致性演算法,就是 Paxos。出自一位 Google 大神之口。Paxos 也是出名的 晦澀難懂,推理過程極其複雜。

Paxos 有點類似之前說的 2PC3PC,但是解決了這兩種演算法各種硬傷。該演算法在很多大廠都得到了工程實踐,比如阿里的 OceanBase分散式資料庫,底層就是使用的 Paxos 演算法。再比如 Googlechubby 分散式鎖 也是用的這個演算法。可見該演算法在分散式系統中的地位,甚至於,Paxos 就是 分散式一致性 的代名詞。

正文

1. Paxos演算法是什麼

Paxos 演算法是 基於訊息傳遞 且具有 高效容錯特性 的一致性演算法,目前公認的解決 分散式一致性問題 最有效的演算法之一.

2. Paxos演算法產生背景

2.1. 拜占庭將軍問題

拜占庭是古代東羅馬帝國的首都,由於地域寬廣,守衛邊境的多個將軍(系統中的多個節點)需要通過信使來傳遞訊息,達成某些一致的決定。但由於信使中可能存在叛徒(系統中節點出錯),這些叛徒將努力向不同的將軍傳送不同的訊息,試圖會干擾一致性的達成。

2.2. Paxos演算法由來

故事背景是古希臘 Paxos 島上的多個法官在一個大廳內對一個議案進行表決,如何達成統一的結果。他們之間通過服務人員來傳遞紙條,但法官可能離開或進入大廳,服務人員可能偷懶去睡覺。

2.3 產生背景

在常見的 分散式系統 中,總會發生 節點當機網路異常 (包括訊息的 重複丟失延遲亂序網路分割槽) 等情況。

Paxos 演算法主要就是解決如何在一個 發生如上故障 的分散式系統中,快速正確的在叢集內 對某個值達成一致,並且保證 整個系統的一致性

分散式理論(五) - 一致性演算法Paxos

3. 演算法詳解

3.1 角色 & 提案

提案 (Proposal)

注意:提案的範圍>value.後面會講到,[提案=編號+Value].也可表示為[M,V]. 以下描述中暫定: 提案=P,Value=V.

角色

  1. Proposer : Proposer 可以 提出提案 (Proposal)。

  2. Accecptor : Acceptor 可以 接受提案。一旦接受提案,提案 裡面的 value 值就被選定了。

  3. Learner : Acceptor 告訴 Learner 哪個提案被選定了,那麼 Learner 就學習這個被選擇的 value

分散式理論(五) - 一致性演算法Paxos

在具體的實現中,一個程式即可能是Proposer,也可能是Acceptor,也可能是Learner。

3.2. 問題描述

Paxos 演算法的核心是 一致性。所以將從一致性問題的描述來講解該演算法怎麼解決實際問題。

3.2.1. 一致性演算法的前置條件

  1. 在被提出的 P 中,只有一個 V 被選中。
  2. 如果沒有 P 被提出,就沒有 V 被選中。
  3. P 被選定後,程式都可以學習被選中的 P

3.2.2. 不同角色通過傳送訊息進行通訊

  1. 每個角色以任意的速度執行,可能因出錯而停止,也可能會重啟。一個 value 被選定後,所有的角色可能失敗然後重啟,除非那些失敗後重啟的角色能記錄某些資訊,否則等他們重啟後無法確定被選定的值。

  2. 訊息在傳遞過程中可能出現 任意時長的延遲,可能會 重複,也可能 丟失,但是訊息不會被 損壞

3.3. 推導過程

3.3.1. 只有一個Acceptor

分散式理論(五) - 一致性演算法Paxos

一個 Acceptor 接受一個 P,那麼只有一個 V 被選定。

問題:如果這個 Acceptor 當機,那麼整個系統服務不可用。

3.3.2. 多個Acceptor

分散式理論(五) - 一致性演算法Paxos

問題:如何在多 Proposer 和多 Acceptor 情況下,選定一個 value?

講解步驟分兩階段:約定 P1約定 P2

3.3.2.1. 約定P1

P1 :一個 Acceptor 必須接受一個它收到的第一個 P。

如果每個 Proposer 會產生不同的 P,那麼多個 Proposer 必定產生多個 P,發給多個 Acceptor。根據 約定 P1Acceptor 分別接受到 P,就會導致不同的 V 被選定,如下圖所示:

分散式理論(五) - 一致性演算法Paxos

如上圖所示,P1 會產生的問題: v1v2v3 都沒有被選定,因為他們只有被一個 Acceptor 接受。

對於上述問題,我們需要一個額外的約定:

P1a : 一個提案 P 被選定,需要被半數以上 Acceptor 接受.

對於 P1a,其實就意味著 一個Acceptor必須接受不止一個提案

顯然,這與 P1 相矛盾,所以需要重新設計提案。原來的設計是: [提案P = value],現在重新設計 [提案P = 提案編號 + value],可表示為 [M,V]

新問題:多提案被選定,如何保證被選定的提案 P 具有相同的value?

3.3.2.2. 約定P2

P2 : 如果提案 P[M0,V0] 被選定了,那麼所有比 M0 編號更高的,且被選定的 P,其 value 的值也是 V0。

對於 P2 中的 “被選定”:一個提案要被選定,首先至少要被一個 Acceptor 批准。因此,可以理解 P2 為:

P2a : 如果提案 P[M0,V0] 被選定了,那麼所有比 M0 編號更高的,且 [被Acceptor批准] 的P,其 value 值也是 V0。

只要滿足 P2a,就能滿足 P2多提案被選擇 的問題解決了,但是由於 網路不穩定 或者 當機 的原因(不可避免),會產生新問題:

分散式理論(五) - 一致性演算法Paxos

假設有 5AcceptorProposer2 提出 [M1,V1]的提案,Acceptor2~5半數以上)均接受了該提案,於是對於 Acceptor2~5Proposer2 來講,它們都認為 V1 被選定。Acceptor1 剛剛從 當機狀態 恢復過來(之前 Acceptor1 沒有收到過任何提案),此時 Proposer1Acceptor1 傳送了 [M2,V2] 的提案 (V2≠V1且M2>M1)。對於 Acceptor1 來講,這是它收到的 第一個提案。根據 P1(一個 Acceptor 必須接受它收到的 第一個提案),Acceptor1 必須接受該提案。同時 Acceptor1 認為 V2 被選定。

這就出現了兩個問題:

  1. Acceptor1 認為 V2 被選定,Acceptor2~5Proposer2 認為 V1 被選定。出現了不一致

  2. V1 被選定了,但是 編號更高 的被 Acceptor1 接受的提案 [M2,V2]valueV2,且 V2≠V1。這就跟 P2a(如果某個 valuev的提案被選定了,那麼每個 編號更高 的被 Acceptor 接受的提案的 value 必須也是 v矛盾了。

基於以上問題,所有就有了 P2b:

P2b : 如果 P[M0,V0] 被選定後,任何 Proposer 產生的 P,其值也是 V0。

對於 P2b 中的描述,怎樣保證 任何Proposer產生的P,其值也是V0 ?只要滿足 P2c 即可:

P2c: 對於任意的 M、V,如果 [M,V] 被提出,那麼存在一個半數以上的 Acceptor 組成的組合 S,滿足以下兩個條件中的任何一個: ① S 中沒有一個接受過編號小於 M 的提案。 ② S 中的 Acceptor 接受過的最大編號的提案的 value 為 V。

推導完畢。。。

3.4. 演算法流程

3.4.1. Proposer提出提案

總體思路如下:

(一). 學習階段:Prepare請求

Proposer 選擇一個新的提案 P[MN,?]Acceptor 集合 S(數目在半數以上)傳送請求,要求 S 中的每一個 Acceptor 做出如下響應:

  1. 如果 Acceptor 沒有接受過提案,則向 Proposer 保證 不再接受編號小於N的提案

  2. 如果 Acceptor 接受過請求,則向 Proposer 返回 已經接受過的編號小於N的編號最大的提案

(二). 接受階段:Acceptor請求
  1. 如果 Proposer 收到 半數以上Acceptor 響應,則 生成編號為 NvalueV 的提案 [MN,V]V 為所有響應中 編號最大 的提案的 value

  2. 如果 Proposer 收到的響應中 沒有提案,那麼 valueProposer 自己生成,生成後將此提案發給 S,並期望 Acceptor 能接受此提案。

3.4.2. Acceptor接受提案

Acceptor 可以忽略任何請求(包括 Prepare 請求和 Accept 請求)而不用擔心破壞 演算法的安全性。因此,我們這裡要討論的是什麼時候 Acceptor 可以響應一個請求。

Acceptor 接受提案給出如下約束:

P1b:一個 Acceptor 只要尚未響應過任何編號大於 N 的 Prepare 請求,那麼就可以接受這個編號為 N 的提案。

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

因此,一個 Acceptor 只需記住:

  1. 已接受的編號最大的提案;
  2. 已響應的請求的最大編號。

分散式理論(五) - 一致性演算法Paxos

4. Paxos演算法描述

分散式理論(五) - 一致性演算法Paxos

5. Learner學習提案

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

分散式理論(五) - 一致性演算法Paxos

6. 如何保證Paxos演算法的活性

分散式理論(五) - 一致性演算法Paxos

小結

Paxos節點當機恢復訊息無序或丟失網路分化 的場景下能保證 資料的一致性。而 Paxos 的描述側重於 理論,在實際專案應用中,處理了 N 多實際細節後,可能已經變成了另外一種演算法,這時候正確性已經無法得到理論的保證。

要證明分散式一致性演算法的正確性通常比實現演算法還困難。所以很多系統實際中使用的都是以 Paxos 理論 為基礎而 衍生 出來的變種和簡化版。例如 GoogleChubbyMegaStoreSpanner 等系統,ZooKeeperZAB 協議,還有更加容易理解的 Raft 協議。

大部分系統都是靠在實踐中執行很長一段時間,經過驗證發現系統已可以基本執行,沒有發現大的問題才能上生產環境。

相關連結

  1. 分散式理論(一) - CAP定理
  2. 分散式理論(二) - BASE理論
  3. 分散式理論(三) - 2PC協議
  4. 分散式理論(四) - 3PC協議
  5. 分散式理論(五) - 一致性演算法Paxos
  6. 分散式理論(六) - 一致性協議Raft

歡迎關注公眾號: 零壹技術棧

image

本帳號將持續分享後端技術乾貨,包括虛擬機器基礎,多執行緒程式設計,高效能框架,非同步、快取和訊息中介軟體,分散式和微服務,架構學習和進階等學習資料和文章。

相關文章