Multi-Paxos Raft 原理 流程

Multi-Paxos Raft

前言

分佈式一致性算法中鼎鼎有名的Paxos算法,有以下的特點

1、理論上證明了是可靠的

2、但是這個證明,這個原理,是真他喵的難懂😂

3、就算真懂了也很難真正實現

4、有live lock的問題

於是人們實在被搞的煩死了,又發明了另一種Multi-Paxos算法:Raft

Raft,相對於Paxos,特點是:

1、沒有理論證明是可靠的

2、容易理解

3、容易實現

4、實踐見真知

 

先看動畫學個大概

http://thesecretlivesofdata.com/raft/

看懂了大概流程之後,我們可以在這裏面玩一下各種情況下最終怎麼保持一致性的:

https://raft.github.io/

玩完之後我們來帶着一些問題看細節:

當有一個機器掛掉了,落後了好多進度,應該怎麼通過這個協議追上來呢?

說明 總覽圖 leader視角 follower視角 數據包

先模擬這個進度落後的情況:

好端端的突然S4掉線了

由於S4掛了,leader拿不到信息了,上次記着他的match index=2,next index = 3

而我們掛掉的S4保存的信息是:commitIndex=2

leader給S4發的請求AppendEntries。prevIndex=2, commitIndex=3,entries=[2]

 

S4知道自己commitIndex=2,然後S1想讓S4commitIndex=3,大概意思就是想讓S4把3這個entry給填成【2】

然後我們把S4重啓 【bring yourself back online 😂】,接收一個來自S1的請求之後

 

然後S1收到了S4的返回,知道S4填好了,就把本地的表給改成S4的match index=3

   

如無意外,這麼搞下去很快S4就會追上進度了。那就來點意外吧😂讓leader掛掉,咱們換個任期。

       

其他人都收不到leader心跳了,會重新選一個leader

S2作爲candidate請求大家給自己投票  
隨後S5也想當leader

S2想當leader,S3 S4同意,S5不同意

但是已經獲得大多數,S2還是成爲了leader;而S5無法獲得多數,競選失敗。

這個過程中,各個節點如果認可新leader,應該會把自己的log信息彙報給新leader,新leader更新自己的peers表。

   

 

在這個戰亂的時刻,我們來關注一下進度跟不上的S4,

somehow S4的matchindex歸爲0了

   
然後S4需要向leader彙報自己的進度,最終也就跟上來了      

 

我們再簡化一下,只有3個機器

說明&總覽 S1 S2 S3
S3經過投票成爲leader,然後接受了2個寫請求並同步完成 follower follower leader

讓S1掛掉,S3接受2寫請求,S1落後進度,這時候S3發4個請求出去,只有1個回,達不到過半數,數據處於半提交狀態。

掛掉 follower

leader

讓S1重新上線,慢慢就恢復了一致性

follower follower leader
       

所以這個協議是怎麼保證最終的一致性呢,落後進度的情況下,有些節點掛掉的情況下,再重啓,怎麼就會好了呢?這些都要通過原理來解釋

 

然後參考下面視頻看看原理

https://www.bilibili.com/video/BV1wt411y7Da/?spm_id_from=333.788.videocard.0

1、客戶端給server發送command

2、server使用paxos協議,選擇command

3、server等待前一個log entries被applied,然後apply一個新的command到狀態機

4、server狀態機的結果給客戶端。

 

解答以下問題:

來了一個客戶端請求,要用哪個log entry?

性能優化:

  • 選個leader來減少proposer 衝突
  • 消除大量的Prepare 請求

保證全部複製好

客戶端協議

配置改變

 

注:這個算法其實沒有得到嚴格的證明,說不定有bug。哈哈哈哈

 

當客戶端的請求到達的時候:

  • 找到第一個還沒被chosen的logEntry
  • 運行basic paxos,propose 客戶端的command
  • prepare請求返回了acceptedValue?
    • yes:選擇acceptedValue,重新開始
    • no:選擇客戶端的command

 

如上圖,先假設server3掉線了,client command=jmp,發到了server1;

server1找到最小的not chosen index = 3,運行paxos,prepare請求,發現server1已經acceptedValue=cmp,那就接受index=3:cmp,然後重新開始

server1找到最小的not chosen index = 4,運行paxos,prepare請求,發現server2已經acceptedValue=sub,那就接受index=4:sub,然後重新開始

server1找到最小的not chosen index = 5,運行paxos,prepare請求,沒發現acceptedValue,終於可以使用client的command。index=5:jmp

選leader:

有最大的id的人當leader

每Tms 每個server發送心跳給其他server

如果一個server在過去的2Tms 沒有收到其他server更高的id,他就成爲了leader:

  • 可以接受客戶端的請求
  • 扮演proposer和Acceptor

如果server不是leader

  • 拒絕客戶端請求,轉發給leader
  • 只能當Acceptor

 

消除Prepares

爲什麼需要prepare?

  • 用來block掉老的proposal
    • 讓proposal number代表整個log,而不是一個entry

 

有點難懂,未完待續。。。。。。。

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