分佈式基礎(6)-分佈式共識之Paxos、Raft算法

本文主要參考自相關書籍和網絡文章,並附上自身的一些理解,如有遺漏或錯誤,還望海涵並指出。謝謝!

一.分佈式共識

之前我們已經瞭解過分佈式系統中會出現的分佈式一致性問題:當分佈式的節點發生了網絡分區時,可用性和強一致性只可選擇一者。

在這裏插入圖片描述

而分佈式共識描述的是分佈式系統中,如何使所有的分佈式節點都達成共識,譬如在節點宕機後,其他的節點如何達成這個節點“已經宕機”的共識?或是要選舉出某個節點作爲Master,那麼其他節點如何達成“該節點作爲Master”的共識?這就是分佈式共識問題。

在分佈式共識問題中,經典的解決方法有Paxos、Raft和ZAB算法。

在此之前,我們需要先了解一下拜占庭將軍問題

https://www.zhihu.com/question/23167269/answer/232108407

11位拜占庭將軍去打仗, 他們各自有權力觀測敵情並作出判斷, 進攻或撤退, 那麼怎麼讓他們只用傳令兵達成一致呢?一種很符合直覺的方法就是投票,每位將軍作出決定後都將結果"廣播"給其餘所有將軍, 這樣所有將軍都能獲得同樣的11份(包括自己)結果, 取多數, 即可得到全軍都同意的行爲.但如果這11位將軍中有間諜呢? 假設有9位忠誠的將軍, 5位判斷進攻, 4位判斷撤退, 還有2個間諜惡意判斷撤退, 雖然結果是錯誤的撤退, 但這種情況完全是允許的. 因爲這11位將軍依然保持着狀態一致性.暫時從戰爭故事中抽離出來, 分佈式數據庫最糟糕的問題絕對不是寫入或者讀取失敗, 而是狀態不同步, 還感知不到. 這個的後果就是correctness不能保證, 那程序就沒有任何意義了.2個間諜怎麼破壞狀態一致性呢? 他們跟5位判斷進攻的將軍說, 我們支持進攻, 那麼這5位將軍統計發現7位支持進攻, 4位支持撤退, 將發動進攻. 又跟4位撤退的將軍說, 我們支持撤退, 一統計, 5票進攻, 6票撤退, 立馬撤退. 這場戰爭必輸無疑了.避免這種狀態不同步的問題, 稱之爲"廣義拜占庭將軍問題"。

簡單地理解這個問題,就是當叛變者不超過 3分之1時,存在有效的算法,使得忠誠的將軍們達到一致的結果。
用數學公式來表達就是,假設節點總數爲 N, 叛變將軍數爲 F, 當 N >= 3F + 1,問題就有解。
Byzantine Fault Tolerant (BFT) 算法就是解決這個問題的。

二.Paxos算法

Paxos算法是分佈式宗師Lamport提出的一種基於消息傳遞的分佈式一致性算法,使其獲得2013年圖靈獎。也是經典的分佈式共識算法,不過由於實現複雜並且偏理論性,並且難於理解,所以主要作爲理論研究居多。

Paxos角色定義

Paxos算法將分佈式系統的節點分爲以下四類角色:

  1. Client(客戶端):系統外部角色,對Proposer發出請求。
  2. Proposer(提議者):接收Client的請求,並提出提案,提案信息包括提案編號和提議的值([n, v])
  3. Acceptor(接收者):接受提案並對提案投票
  4. Learner(告知者):被告知對提案的投票結果,不參與投票過程

1.Basic Paxos

Basic Paxos是一種基本的Paxos算法變種,實現比較簡單。

1.算法步驟
  • 一階段:Prepare,Proposer提出一個提案,編號爲n,該編號大於Proposer之前提出的提案編號則請求Acceptor接受提案
  • 一階段:Promise,如果n大於該Acceptor之前接受的提案編號則接受,否則拒絕
  • 二階段:Accept,如果大多數Acceptor同意該提案,則Proposer會發出Accept請求,此請求包含了該提案編號n和提案內容
  • 二階段:Accepted,如果Acceptor在Accept期間沒有接收到任何編號大於n的提案,則接收此提案內容,否則忽略
2.基本流程

現在演示Basic Paxos的基本請求流程:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xRRMcY5a-1585668479376)(http://note.youdao.com/yws/res/17884/9AECDAA3A1554EB9955795F53E257D99)]

  1. Client向Proposer發送請求
  2. Proposer進入Prepare階段,對Acceptor發出提案(編號爲1)
  3. Acceptor接收到提案,進入Promise階段,假設a、b、c三個Acceptor都同意該提案(Promise(1, {Va, Vb, Vc}))
  4. 大多數Acceptor都同意該提案,Proposer向Acceptor發出Accept請求(提案內容爲Vn)
  5. 在這個期間沒有其他新的提案產生,所以Acceptor接受此提案,進入Accepted階段,然後告知Learner記錄結果
  6. Learner記錄下結果後,響應Client
3.部分節點失敗

上述的基本流程是最理想的情況下,全部Acceptor都同意提案的情況,接下來演示的是部分節點失敗(不同意提案或者是Acceptor節點宕機)時的Basic Paxos流程:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6xoFe15n-1585668479377)(http://note.youdao.com/yws/res/17899/49CBD11108664700A00FE47FC49C5BBD)]

  1. Client向Proposer發送請求
  2. Proposer進入Prepare階段,對Acceptor發出提案(編號爲1)
  3. Acceptor接收到提案,進入Promise階段,此時有一個Acceptor不同意或宕機,但是仍然有兩個節點同意,滿足大多數同意提案的情況(Quoroms Agree)
  4. Proposer向Acceptor發出Accept請求(提案內容爲V)
  5. 在此期間沒有其他的提案,所有Acceptor同意提案(Accepted),並告知Learner記錄結果,響應給Client
4.Proposer失敗

現在來看看Basic Paxos中,Proposer失敗的場景。由於Proposer也是一個節點,所以有可能出現宕機的問題。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VkFuwM40-1585668479378)(http://note.youdao.com/yws/res/17918/08BDF8C0EAFC4DCE97CBC96745FE0605)]

  1. Client向Proposer發送請求
  2. Proposer進入Prepare階段,對Acceptor發出提案(編號爲1)
  3. Acceptor接收到提案,進入Promise階段,假設a、b、c三個Acceptor都同意該提案
  4. Proposer失敗
  5. 此時會重啓另一個Proposer,來重新發送提案,繼續執行Prepare、Promise、Accept和Accepted的過程
5.活鎖問題

Basic Paxos在多個Proposer的情況下會出現活鎖問題,導致整個系統不能正常工作,出現對多個提案進行競爭Accept的情況。

https://zhuanlan.zhihu.com/p/31780743
在這裏插入圖片描述

2.Multi Paxos

爲了解決Basic Paxos的多個提案下的活鎖問題和需要兩個階段的網絡來回問題,此時出現了Paxos算法的另一種變種:Multi Paxos

0.Leader

在Multi Paxos中,只有一個Proposer可以對Acceptor提出提案,該proposer被稱爲Leader。

1.算法步驟

在這裏插入圖片描述

  1. Leader確認階段:其中一個Proposer對Acceptor發送一個提案,提案中帶有n標誌着這是某個Proposer節點(Prepare);Acceptor對這個Proposer進行確認(Promise),然後該Proposer發出Accept請求,確定自身爲Leader(Accepted)
  2. 請求階段:在該Leader的有效期內,對Acceptor發送請求,但是無需再進行Prepare和Promise階段,Acceptor會同意該Leader的提案,直接進入Accepted階段,然後Acceptor響應Learner記錄該提案響應客戶端,並告訴Leader
2.角色優化

對於Multi Paxos算法,可以將Proposer和Acceptor角色給合併爲一個角色Servers:

在這裏插入圖片描述

這樣,Client向Servers中選舉出來的Leader發送請求,然後Leader向其他Server節點重複Leader確認階段和請求階段即可。

3.Multi Paxos的優點
  1. 首次請求進行Proposer的Leader選舉後,Client的所以請求都由該Leader發送,不會出現活鎖現象
  2. 選舉出Leader後,Leader發送的請求只需要一輪網絡RPC即可(直接進入Accept和Accepted階段)

三.Raft算法

由於Paxos算法實在太複雜,並且難於實現,所以產生了Raft算法。Raft算法可以視爲Multi Paxos算法的精簡版本,易於理解和實現。

關於Raft的動畫演示可以參考該網站:

http://thesecretlivesofdata.com/raft/

1.角色定義

  • Client:系統外部客戶端
  • Leader:負責接受Client的寫請求,並將寫請求同步到所有的Follower
  • Follower:同步於Leader的數據
  • Candidate:當一定時間內不存在Leader時,會有相應的Follower成爲候選者進行Leader選舉

2.核心流程

1.Leader Selection

Raft將Leader選舉和Log複製過程分開成兩個部分,分別進行。首先會進行Leader選舉,選舉出系統中的Leader。

1.1、初始化Leader

在系統剛啓動時,所有的節點都將被視爲Follower,這時需要初始化一個節點作爲Leader。

首先,每個節點都擁有兩個超時時間,第一個超時時間爲選舉超時時間(選舉超時時間會在150ms到300ms之間隨機分配),這個時間是Follower成爲Candidate之前所等待的時間,當Follower變成了Candidate,成爲Candidate的節點將會向其他節點發送信號,建議自己成爲Leader。當該Candidate獲取到大多數的投票時,自身變爲Leader。

選舉超時時間在流逝,每個節點的超市時間都不相同
在這裏插入圖片描述
C節點的超時時間已到,成爲候選人
在這裏插入圖片描述
C節點向其他節點發送請求,建議投票自己成爲Leader
在這裏插入圖片描述
在這裏插入圖片描述
在C節點作爲Leader期間,C節點會不斷地向其他節點發送心跳包,刷新其他節點的選舉超時時間
在這裏插入圖片描述

1.2、重新選舉Leader

當C節點宕機後,不會再向其他節點發送心跳包,這時A和B的選舉超時時間會不斷流逝
在這裏插入圖片描述
A節點的選舉超時時間流逝完,變爲候選者,向B節點發送請求,建議投票給自身,A成爲Leader
在這裏插入圖片描述

1.3、雙候選人選舉

加入現在有4個Follower節點的選舉超時時間正在流逝
在這裏插入圖片描述
此時C、D節點同時成爲候選者,然後向其他節點發送建議投票的請求
在這裏插入圖片描述
C、D此時接收到的響應應該是相同的,也就是得票數相等
在這裏插入圖片描述
此時C、D會同時刷新150ms~300ms的選舉超時時間,重複選舉的過程
在這裏插入圖片描述
此時D先結束了選舉超時時間,所以向其他節點發送建議投票請求,D成爲了Leader
在這裏插入圖片描述

2.Log Replication

在這裏插入圖片描述

節點經過Leader選舉過程之後會產生一個Leader,Client的寫服務要經過Leader,Leader首先對其他Follower發送心跳包判斷是否超過半數的Follower能夠同步這次寫操作,當半數以上的Follower能夠同步到這次寫操作,則表示寫入成功,進行日誌複製;若不能完成,則寫入失敗。

注意,Leader向其他Follower發送Log同步請求時,實質上也是一個心跳包,這裏心跳包的作用一是攜帶請求,而是刷新Follower的選舉超時時間。

1.Log複製過程

Client向Leader B發送Set 5這個寫請求
在這裏插入圖片描述
Leader B向其他Follower發送心跳包,確認是否可以同步
在這裏插入圖片描述
一旦大多數的Follower可同步,則執行Set操作
在這裏插入圖片描述
然後Leader B將寫入成功的響應發送給客戶端,然後其他的Follower會同步這個操作
在這裏插入圖片描述

2.網絡分區發生

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CnsPLWTn-1585668479398)(http://note.youdao.com/yws/res/18114/44FAB679A9E14D45A98B364E17E23AEB)]

注意,Leader選舉需要半數以上的Follower同意纔行,一般節點數量應該選擇爲奇數,因爲這樣才能在網絡分區發生時能夠正常地進行Leader選舉。

假設現在系統發生了網絡分區,此時A、B被劃分到了一個分區中,C、D、E被劃分到了另一個分區中
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yYaQYU5e-1585668479399)(http://note.youdao.com/yws/res/18117/57883DCBBB03491A84E2727A14C668B8)]
這時由於C、D、E的選舉超時時間流逝,其中C成爲候選人,向D、E節點發送投票請求,C成爲所在分區的Leader
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3LTBwQF7-1585668479400)(http://note.youdao.com/yws/res/18123/D000DA4AEDFB455AB7064645FB0736A1)]
此時客戶端1向Leader B發生Set 3的請求,Leader B會發送心跳包給A,確認其是否可以同步,但是卻發現當前只有2個節點同意同步(包括Leader B自身),達不到節點總數的一半以上(不到3個),所以暫時不會進行數據的更新
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QAsArfpL-1585668479403)(http://note.youdao.com/yws/res/18129/015D3452E3B14EDD9367778870F112E3)]
此時客戶端2向Leader C發送了一個Set 8的請求,Leader C把心跳包發送給D
和E,目前半數以上節點(3個節點)都可同步數據,所以提交日誌,C、D、E節點被設置爲8
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BMRVKBWJ-1585668479404)(http://note.youdao.com/yws/res/18133/F2FC787B762241F0A9FBAE7B369D1DA5)]
當網絡分區消除後,A節點發現自身的Leader年代比C的小(Term),所以把自身設置爲Follower,接受C的同步,將數據同步到其他節點的狀態
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-89YhwYGs-1585668479404)(http://note.youdao.com/yws/res/18140/9A8DDE42A2974E5AAA8FDB04C2D8E095)]

四.總結及推薦

看完了Basic Paxos、Multi Paxos和Raft算法的基本原理和過程,現在來做一個總結回顧和學習資源推薦哈。

Paxos算法是分佈式共識領域一個十分重要的理論算法,它的實現複雜,要求苛刻,並且具備許多變種,譬如Basic Paxos和Multi Paxos。

Paxos算法需要定義的核心角色有:

  1. Proposer(提議者):接收Client的請求,並提出提案,提案信息包括提案編號和提議的值([n, v])
  2. Acceptor(接收者):接受提案並對提案投票
  3. Learner(告知者):被告知對提案的投票結果,不參與投票過程

Basic Paxos算法的實現過程需要兩階段RPC:

  • 一階段Prepare過程,Proposer將提案提交給Acceptor
  • 一階段Promise過程,Acceptor對提案進行投票
  • 二階段Accept過程,當大多數Acceptor對提案進行了同意投票,那麼Proposer會對Acceptor發出Accept請求
  • 二階段Accepted過程,Acceptor接收到Proposer的Accept請求,判斷這個過過程中沒有其他的提案產生,允許該提案。Acceptor將提案發給Learner進行記錄,並且響應給Proposer和客戶端

Basic Paxos在多個Proposer提出多個提案的過程中,可能發生活鎖。

Multi Paxos的算法相較於Basic Paxos更加簡單並且易於實現,是Paxos的一種工程化變種。

Multi Paxos算法需要確認一個Proposer作爲Leader,也只有這個Leader能夠向Acceptor發送提案。在第一次建立對Leader的信賴後,後續的提案過程中都不需要進行一階段Prepare、Promise過程,而是直接進行二階段的Accept和Accepted過程,減少了一輪RPC調用,並且解決了活鎖問題。

Raft算法是Multi Paxos算法的精簡實現,由於其簡單易實現,被廣泛用於分佈式系統之中,譬如Redis就是使用Raft算法來做哨兵集羣的Leader選舉的。

Raft算法的核心角色爲:

  • Leader:接受Client的寫請求並將其同步給其他大部分Follower
  • Follower:同步Leader的數據
  • Candidate:當節點的選舉超時時間流逝後,變爲候選者,參與Leader選舉

Raft算法分爲兩個核心的過程,分別是Leader選舉過程和日誌複製過程。

Leader選舉過程:

  • 初次選舉
  • 宕機選舉
  • 雙候選者選舉

Log複製過程:

  • 大部分Follower可以同步纔算寫成功
  • 網絡分區時的同步,以大部分節點的那個分區Leader爲真實Leader

推薦的學習資源

  • 一致性算法(Paxos、Raft、ZAB):https://www.bilibili.com/video/BV1TW411M7Fx
  • 分佈式系統以及共識機制:https://www.jianshu.com/p/c49bbf8630df
  • Raft算法在線調試:https://raft.github.io/
  • Raft算法在線演示:http://thesecretlivesofdata.com/raft/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章