強一致性算法Paxos、Raft、ZAB

在B站上一個講這三個算法的視頻網址https://www.bilibili.com/video/av21667358

Paxos協議

Basic paxos算法中,分爲4種角色:

  • Client: 系統外部角色,產生議題者,像民衆
  • Proposer :接收議題請求,像集羣提出議題(propose),並在衝突發生時,起到衝突調節的作用,像議員
  • Acceptor:提議的投票者和決策者,只有在形成法定人數(一般是majority多數派)時,提議纔會被最終接受,像國會
  • Learner:最終提議的接收者,backup,對集羣的已執行沒有什麼影響,像記錄員

Paxos有三種實現版本

  1. Basic Paxos版本
  2. Multi Paxos版本
  3. Fast Paxos版本

兩個階段

Prepare階段

  1. Proposer 生成提案編號 Mn, 向Quorum 廣播該編號。
  2. Acceptor 收到Prepare Mn 之後
    1. 如果比已接受提案編號大,則接受Mn, 並承諾不再接受小於Mn 的提案,將已接收的編號最大提案通過返回ACK 給Proposer。
    2. 否則忽略Prepare Mn
  3. Proposer 收到Quorum 數量的ACK 之後,則進入提交階段。否則重新開始Prepare 階段。

Accept階段

  1. Proposer 選取ACK 中編號最大的提案的Value 作爲Vn, 向Quorum 廣播 Accept [Mn, Vn]。
  2. Acceptor 收到Accept [Mn, Vn] 之後
    1. 若提案不違背承諾,則接受該提案,並返回ACK
    2. 否則忽略

Basic Paxos版本

該版本是最基本的版本,由多個proposer和多個acceptor組成

該版本的問題是,

  • 一個完整的事務,需要兩次RPC遠程調用,分別是Prepare階段和Accpet階段。效率不高
  • 因爲是多個proposer可以都提交提案,因此會出現活鎖問題,Proposer1提出了M1的提案,並完成的Prepare階段。與此同時,Proposer2提出了一個新的提案M2(M2>M1),同樣也完成了Prepare階段,於是Acceptor承諾不再批准編號小於M2的提案。當P1進入Accept階段時,其發出的Accept請求將被Acceptor忽略。於是Proposer1再次進入Prepare階段並提出一個編號爲M3(M3>M2)的提案,而這又會讓Proposer2的M2在第二階段的Accept請求被忽略,如此陷入死循環

Multi Paxos版本

該版本只有一個Leader Proposer,只有Leader Proposer可以提出提案,Leader Proposer通過選舉產生。

選舉一個Leader Proposer的時候,需要進行投標,當一個Leader選舉出來之後,該Leader發出的提案就可以直接進入Accpet階段。

Raft協議

raft 簡化版的Multi Paxos,劃分了三個子問題

  • Leader Electtion
  • Log Replication
  • Safety

重定義了三個角色

  • eader
  • Fllower
  • Candidate

這個解釋的非常明白
原理動畫解釋:https://http://thesecretlivesofdata.com/raft/

這個是怎樣選舉的leader,某個節點宕機了怎麼解決的詳細動畫演示
場景測試:http://raft.github.io

ZAB協議

基本與Raft相同,在一些名詞叫起來是有區別的

ZAB將Leader的一個生命週期叫做epoch,而Raft稱之爲term

實現上也有些許不同,如raft保證日誌的連續性,心跳是Leader向Follower發送,而ZAB方向與之相反

術語說明:

ZXID:高32位是epoch,表示Leader週期,單調遞增;低32位,Leader產生一個新的事務proposer時,該計數器會加1(在一個Leader週期裏是單調遞增,epoch變更後從0開始)

SID:服務器ID,用來唯一標識一臺ZooKeeper集羣中的服務器,每臺機器不能重複,和myid的值一致。

vote_sid:接收到的投票信息中所推舉的Leader服務器的SID

vote_zxid:接收到的投票信息中所推舉的Leader服務器的ZXID

self_sid:當前服務器自己的SID

self_zxid:當前服務器自己的ZXID

electionEpoch:當前服務器的選舉輪次。

Leader選舉

1.變更狀態:如果是運行過程中Leader掛了,則會有這一步,非Observer服務器會將自己的服務器狀態變更爲LOOKING(尋找Leader狀態),然後進入Leader選舉流程

2.每個Server會發出一個投票 vote[self_id,self_zxid]

3.接收來自各個Server的投票 vote[vote_sid,vote_zxid]

4.處理投票

  •   先比較ZXID,ZXID比較大的服務器優先作爲Leader

         如果vote_zxid > self_zxid,就認可收到的投票,並再次將該投票發送出去

         如果vote_zxid < self_zxid,就堅持自己的投票,不做任何變更

  •   如果ZXID相同的話,那麼比較myid,myid比較大的服務器作爲Leader服務器。

          如果vote_sid > self_sid,就認可收到的投票,並再次將該投票發送出去

          如果vote_sid < self_sid,那麼就堅持自己的投票,不做任何變更

5.統計投票:判斷是否已經有過半的機器Quorum接收到相同的投票信息,如果存在一個服務器得到過半的票數,那麼得到過半票數的機器作爲Leader,終止投票。否則進入步驟3,進入到新一輪的投票選舉中。

6.改變服務器狀態:確定Leader後,每個服務器會更新自己的狀態,如果是Follower,那麼就變更爲FOLLOWING(跟隨者狀態),如果是Leader,那麼就變更爲LEADING(領導者狀態)

         注意:選舉出一個leader後,服務器不會馬上更新狀態,而是會等待一段時間(默認是200毫秒)來確定是否有新的更優的投票。

Leader同步

由於上述選舉過程保證了 Leader 必然擁有最大zxid, Leader 只需要向Follower 同步自己的歷史提案即可。

  1. 若Follower 擁有 Leader 沒有的提案,則 truncat掉。
  2. 若Follower的epoch = 當前leader的epoch,落後則根據log, reply 歷史transcation
  3. 若落後太多,則直接同步 snapshot,再replay transaction log.

參考理解分佈式一致性:Paxos協議之Multi-Paxos

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章