分布式共識算法 (二) Paxos算法


 系列目錄

分布式共識算法 (一) 背景

分布式共識算法 (二) Paxos算法

分布式共識算法 (三) Raft算法

分布式共識算法 (四) BTF算法

 一、背景

1.1 命名

Paxos,最早是Leslie Lamport 用Paxos島的故事模型進行描述,而得以命名。這位大神原來是學數學的,最終變成了計算機科學家,在2013年獲得圖靈獎...附上美照:

1.2 Paxos問題

Paxos問題是指分布式的系統中存在故障(crash fault),但不存在惡意(corrupt)節點的場景(即能消息丟失/重復,但無錯誤消息)下的共識達成問題。

1.3 Paxos協議

Paxos 協議是一個解決分布式系統中,多個節點之間就某個值(提案)達成一致(決議)的通信協議

1990年Leslie Lamport在論文《The Part-time Parliament》中提出Paxos共識算法,在工程角度實現了一種最大保障分布式系統一致性的機制。Paxos算法被廣泛應用在Chubby、ZooKeeper中。

Paxos wiki:Paxos (computer science)

二、Paxos算法

2.1 角色(核心就3個角色)

Client:客戶端,發起請求並等待返回。
Proposer案者):處理客戶端請求,將客戶端的請求發送到集群中,以便決定這個值是否可以被批准。
Acceptor(接受者):負責處理接收到的提議,他們的回復就是一次投票。會存儲一些狀態來決定是否接收一個值。
Learner(學習者):當有同一個value的協議被超過一半的Acceptor采納並發送消息給Learner時,Learner采納該協議值。
Leader:一個特殊的Proposer。

2.2 Basic-Paxos算法

核心實現Paxos Instance主要包括兩個階段:

准備階段(prepare phase)和提議階段(accept phase)。細化為4個小階段,wiki上是這樣描述的:

簡單來說,Basic Paxos 是一個經典兩階段提交(2PC)

第一階段

  • 1a prepare 准備: proposer向acceptors提出一個協議,這里的協議就是期望的“一致性內容”
  • 1a promise 承諾: acceptor承諾只接收最大協議號的協議(包括prepare和accept),並拒絕比當前協議號N小的協議,回復proposer之前接收的所有協議值。如果當前協議號N比之前都小,那么回復拒絕。

第二階段

  • 2a Accept Request 發起“accept”請求:proposer收到acceptor反饋的足夠的承諾后,給協議設最大值,如果沒回復,隨便設置一個值。發送"accept"請求給選定值的acceptors.
  • 2b Accepted: acceptor接受協議(該acceptor之前沒有承諾過大於該協議號的協議),並通知給proposer和learner.

    配上wiki流程圖如下:

其中prepare階段的作用,如下圖所示:

1.S1首先發起accept(1,red),並在S1,S2和S3達成多數派,red在S1,S2,S3上持久化
2.隨 后S5發起accept(5,blue),在S3,S4和S5達成多數派,blue在S3,S4和S5持久化
4.最后的結果是,S1和S2的值是red,而S4和S5的值是blue,s3存在異議,red覆蓋了blue?

解決方案:

  • 1.將提議進行排序,可以為每個提議賦予一個唯一的ID,規定這個ID越大越新,很明顯(5,blue)和(1,red),5比1大,所以保留blue
  • 2.采用兩階段方法,拒絕舊提議

2.3 Muti-Paxos算法

很多文章有誤解說Muti-Paxos是一階段提交,那是僅限於leader穩定時。剛選出來一個新的leader時,依然是二階段提交如下圖:

 如果leader穩定不需要prepare和promise步驟,如下圖(圖中Proposer就是一個Leader):

Multi Paxos中leader用於避免活鎖(例如1個leader,4個Proposer,2個提議A,2個提議B不能達成一致,導致活鎖),但leader的存在會帶來其他問題,一是如何選舉和保持唯一leader(雖然無leader或多leader不影響一致性,但影響決議進程progress),二是充當leader的節點會承擔更多壓力,如何均衡節點的負載。Mencius[1]提出節點輪流擔任leader,以達到均衡負載的目的;租約(lease)可以幫助實現唯一leader,但leader故障情況下可導致服務短期不可用。

2.4 Muti-Paxos在google chubby中的應用

Google Chubby是一個高可用分布式鎖服務,被設計成一個需要訪問中心化節點的分布式鎖服務。本文只分析chubby服務端的實現。

 Chubby服務端的基本架構大致分為三層

  ① 最底層是容錯日志系統(Fault-Tolerant Log),通過Paxos算法能夠保證集群所有機器上的日志完全一致,同時具備較好的容錯性。

  ② 日志層之上是Key-Value類型的容錯數據庫(Fault-Tolerant DB),其通過下層的日志來保證一致性和容錯性。

  ③ 存儲層之上的就是Chubby對外提供的分布式鎖服務和小文件存儲服務。

 

 Paxos算法用於保證集群內各個副本節點的日志能夠保持一致,Chubby事務日志(Transaction Log)中的每一個Value對應Paxos算法中的一個Instance(對應Proposer),由於Chubby需要對外提供不斷的服務,因此事務日志會無限增長,於是在整個Chubby運行過程中,會存在多個Paxos Instance,同時,Chubby會為每個Paxos Instance都按序分配一個全局唯一的Instance編號,並將其順序寫入到事務日志中去。

  在Paxos中,每一個Paxos Instance都需要進行一輪或多輪的Prepare->Promise->Propose->Accept這樣完整的二階段請求過程來完成對一個提議值的選定,為了保證正確性的前提下盡可能地提高算法運行性能,可以讓多個Instance共用一套序號分配機制,並將Prepare->Promise合並為一個階段。具體做法如下:

  ① 當某個副本節點通過選舉成為Master后,就會使用新分配的編號N來廣播一個Prepare消息,該Prepare消息會被所有未達成一致的Instance和目前還未開始的Instance共用。

  ② 當Acceptor接收到Prepare消息后,必須對多個Instance同時做出回應,這通常可以通過將反饋信息封裝在一個數據包中來實現,假設最多允許K個Instance同時進行提議值的選定,那么:

  -當前之多存在K個未達成一致的Instance,將這些未決的Instance各自最后接受的提議值封裝進一個數據包,並作為Promise消息返回。

  -同時,判斷N是否大於當前Acceptor的highestPromisedNum值(當前已經接受的最大的提議編號值),如果大於,那么就標記這些未決Instance和所有未來的Instance的highestPromisedNum的值為N,這樣,這些未決Instance和所有未來Instance都不能再接受任何編號小於N的提議。

  ③ Master對所有未決Instance和所有未來Instance分別執行Propose->Accept階段的處理,如果Master能夠一直穩定運行的話,那么在接下來的算法運行過程中,就不再需要進行Prepare->Promise處理了。但是,一旦Master發現Acceptor返回了一個Reject消息,說明集群中存在另一個Master並且試圖使用更大的提議編號發送了Prepare消息,此時,當前Master就需要重新分配新的提議編號並再次進行Prepare->Promise階段的處理。

  可見chubby就是一個典型的Muti-Paxos算法應用,在Master穩定運行的情況下,只需要使用同一個編號來依次執行每一個Instance的Promise->Accept階段處理。

  

三、總結

Paxos算法的變種還有很多Cheap PaxosFast Paxos等等,本文介紹了使用最廣的Muti-Paxos算法。希望能夠帶給大家一點分布式一致性算法的入門靈感和思想。

 

 

====================

參考:

1.paxos的wiki:Paxos (computer science)

2.csdn博客:一步一步理解Paxos算法

3.書:《從Paxos到Zookeeper》

4.論文:《Time-Clocks-and-the-Ordering-of-Events-in-a-Distributed-System》

5.書:《區塊鏈 原理、設計與應用》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM