分佈式與併發【四】淺談分佈式一致性算法Raft

前言

之前簡單介紹過Paxos算法,並且推導了整個算法的產生,說明了實現過程,但是顯而易見Paxos算法非常難理解,並且更難以實現,Raft算法的出現用來代替Paxos算法,實現更加容易,由於本人水平有限,可能文中出現錯誤,還請大家指出。

基礎概念介紹

Raft是一種用於管理複製日誌的一種一致性算法,它將通過一些功能將一致性的一些問題分解,從而更方便理解。

一、Raft的重要功能

Leader選舉、日誌複製(數據同步)、日誌壓縮(數據快照)、安全性等等

二、Raft的角色

Raft算法中將服務節點分爲了三種角色:

Leader(領導者): 主服務節點,用來處理客戶端的請求,並且將數據同步到Follower節點,只有當大多數Follower節點複製成功後纔算數據寫入成功。
Follower(跟隨者):從服務節點,用來保持和Leader的數據同步,並且接受Leader心跳,當超過一定時間沒有收到心跳則發起選舉流程。
Candidate(候選者):當選舉階段發生時,Follower發起選舉並將自身更新爲候選者的角色,該角色只在選舉階段出現。

三、Leader任期(Term)

Raft算法將整個服務的時間劃分爲一個個Term週期,每個Term週期也就是Leader所當選的任期,該任期通過一個連續的數字來表示,每個任期開始的時候都會選舉一個新的Leader來帶領其他Follower,如果一個新的任期沒有選舉出Leader則Term+1,開始下一個任期的選舉,通常具有最新任期的節點視爲擁有最全的數據。

Raft保證在一個任期期間,最多隻有一個Leader。

簡單來說就像是總統的選舉,每個任期爲5年,當出現一些情況時,會進行總統的重新選舉,也自然到達一個新的任期。

四、服務通信

在Raft算法中,各個不同節點之間的通信使用的是RPC協議,在整個算法中的通信分爲以下三種

  • RequestVote:選舉投票請求,主要在Leader選舉期間發生。
  • AppendEntries:Leader發起的心跳,並且也同時進行日誌的複製。
  • InstallSnapshot:Leader向Follower同步日誌快照信息,主要用來新加入的Follower節點和日誌同步落後太多的節點與Leader同步數據。

Leader選舉

一、什麼是Leader的選舉?

Raft算法規定了,只有Leader節點才能處理讀寫請求,Follower節點只進行數據的同步和Leader的選舉。選舉時採用RequestVote RPC通信

在服務器啓動運行時刻,所有節點默認都爲Follower角色,然後會等待一段時間沒有收到Leader的心跳,則延遲隨機時間來進行角色轉化(Candidate)發起選舉。
爲什麼需要延遲隨機時間,這是爲了多個Candidate節點同時發起選舉,會造成選票分票導致無法選舉成功,而延遲一段隨機時間可以提高選舉成功率。

在服務的運行當中,如果一個Follower節點與Leader節點失聯超過一個Term週期,則Follower自動轉化爲Candidate角色,發起Leader的新一個Term任期選舉,並且優先選自己作爲Leader。選舉發起時,Candidate請求其他節點投票給自己,如果收到了大多數節點的投票,則當選Leader開始一個新的Term任期,其他節點則更新自己的Term爲最新任期,在Leader的任期期間,會持續的發送心跳(AppendEntries)來維持自己的Leader地位。

二、超時

通過上述選舉描述,可以看到有兩種超時時間:

  1. 選舉超時:也就是每個Follower節點隨機延遲的時間,用來避免選票分票、提高選舉成功率。
  2. 心跳超時:也就是Leader節點持續發送心跳的時間,如果Follower接受心跳超時,則會進行新一輪的選舉。
三、選舉的條件

在進行Leader選舉投票時,如何確定該給誰投票呢?Raft規定了下面幾個優先級。

  1. Term最大的優先
  2. 如果Term相同,則具有最新日誌編號(LogIndex)的
  3. 如果LogIndex也相同,選擇最先發起投票的

而一個Leader如何放棄自己的Leader地位呢?
如果遇到Term比自己大的節點,則放棄Leader地位,轉爲Follower。
這是因爲可能由於網絡分區,導致新的Leader節點產生,而恢復後應該與最新的Leader保持同步,避免腦裂。

四、選舉流程

首先我們默認有一個5節點構成的分佈式集羣,然後描述服務的選舉流程

1、服務器初始階段
初始化選舉
可以看到,在初始階段,沒有leader節點,大家都不會收到Leader的心跳,這時候每個節點維護自己的隨機選舉超時時間,這時候S5節點由於時間最短,轉化爲Candidate發起選舉,當選Leader並且維護自己Term任期。

2、Leader宕機或網絡分區選舉
Leader宕機
通過上圖可以看到,在Term爲1的任期期間,收到了客戶端10條操作日誌,並且同步給了其他四個節點,其中S1和S3同步最新,而Logindex10還沒有進行提交。如果此時S5節點宕機,S1-S4節點無法收到心跳,則發起新一輪的Leader選舉。那麼誰將會當選Leader呢?

根據Raft選舉條件限制:
(1)S2和S4由於數據同步較慢,肯定無法當選Leader
(2)由於S1和S3任期相同,Logindex也相同,根據選舉超時時間,由S3先發起選舉投票,則最終由S3當選。
(3)而由於Logindex=10並沒有被大多數節點提交,所以並不會返回給客戶端10這條記錄更新成功。最新的數據依然爲9

3、原Leader恢復
Leader恢復
通過上圖可以看到,S3當選了Leader後對外持續提供服務,並且爲新的任期Term = 2 ,此時S5恢復了,S5原先爲Leader當發現新的Term比自己大時,降級爲Follower節點和Leader同步數據。

日誌複製

日誌複製是保證數據一致性的重要組成部分,由於Leader節點才能處理數據寫請求,所以如何保證其他Follower節點也能同步數據呢?

日誌複製階段,也就是心跳持續發送階段採用AppendEntries RPC通信

一、日誌複製概念

(1)客戶端每一次數據更新,都有一條對應的日誌記錄LogIndex,並且由Term和執行命令組成。
(2)如果Logindex被大多數機器複製成功,便認爲可以提交了,此時由Leader更新狀態機向客戶端返回成功。
(3)日誌會被持久化到磁盤當中,保證持久性
(4)如果不同的日誌中存在兩條相同的任期號和索引編號,則認爲存儲的命令是一致的。因爲leader 最多在一個任期裏的一個日誌索引位置創建一條日誌條目,日誌條目在日誌的位置從來不會改變。
(5)日誌的創建是有序的。
(6)日誌在一些異常情況下可能會被覆蓋。

二、日誌複製流程

(1)在Leader向Follower發送心跳時,會同時帶着需要複製的日誌消息體Entries與當前日誌的前一條日誌Entries,用來做簡單的一致性校驗(前一條相同纔可以)。
(2)當存在Follower日誌與Leader不一致時,通過強制Follower覆蓋爲Leader日誌來保證一致性,具體是:Leader從Follower最後一條日誌向前依次判斷,找到相同日誌的位置然後進行覆蓋。

正常情況流程:

正常情況就沒什麼可以說的,只要Leader發送心跳時,同步複製日誌即可

異常情況流程:

(1)網絡分區
在這裏插入圖片描述
如上圖所示,當發生網絡分區時,S1和S5無法與其他節點進行通信,導致V2這條日誌數據無法同步複製給大多數節點,導致V2無法更新成功這時候由於S2\S3\S4無法收到Leader的心跳,開始新一輪的選舉,假設S2當選Leader。

(2)Leader選舉
在這裏插入圖片描述
如上圖所示,在S2任期期間收到了並且同步了V3\V4日誌,此時當S1和S5恢復後發現數據不一致,這時S1會自動降級爲Follower節點,並且強制從V1日誌開始進行數據覆蓋同步。

(3)日誌覆蓋
在這裏插入圖片描述
上述情況只是簡單的介紹了數據不一致的情況,其實一個Follower可能會丟失掉Leader上的一些條目,也有可能包含一些Leader沒有的條目,也有可能兩者都會發生。丟失的或者多出來的條目可能會持續多個任期。

節點新增:
當新加入一個節點時,直接同Leader複製日誌即可。

日誌壓縮

由於日誌的記錄不可能無限制的增加,這樣非常影響回放效率,影響可用性,所以Raft採用了SNAPSHOT快照的方式來對日誌進行壓縮,這樣快照之前的日誌都可以不用再進行存儲。

其中在做SNAPSHOT快照時,每個副本都會對自己當前的系統狀態和已經提交日誌做壓縮快照。

快照載入使用InstalledSnapshot RPC通信完成。

快照的組成
  1. 日誌元數據,最後一條已提交的 log entry的 log index和term。這兩個值在SNAPSHOT之後的第一條log entry的AppendEntries RPC的完整性檢查的時候會被用上。
  2. 系統當前狀態。
快照的頻率

由於快照生成非常消耗CPU,所以不建議太過頻繁,而是採用當日志到達一定大小後進行快照生成。

快照的載入回放

在生成快照後什麼時候纔會使用呢?

  1. 新節點加入:在一個新節點加入集羣時,通過快照來進行快速的載入
  2. 落後太多的節點:有時候Follower落後了太多,無法通過日誌來進行覆蓋的時候,採用快照先進行數據載入

總結

通過上面已經比較清楚的理解了Raft算法。
接下來通過幾個問題來進行總結

Raft和Paxos的區別?
  1. 其中相對於Paxos,Raft更好理解也更容易實現。
  2. Paxos是一種通用的解決分佈式一致性的算法,Raft進行了擴展優化。
  3. Paxos可以有多個發起提案的節點,Raft只有Leader發起
  4. multi-Paxos任意節點可以當選Leader,Raft只有最新提交日誌的當選。
  5. Raft對每一次選舉都有Term任期號
Raft的特點
  1. Raft每一次數據提交都有Logindex編號和Term任期號
  2. 整個日誌由有序的日誌條目組成
  3. Raft選舉時,每個節點具有隨機時間,大幅度避免了選票分票情況。
Raft主要由哪幾部分組成?
  1. Leader選舉
  2. 日誌複製
  3. 日誌壓縮等
Raft PreVote機制作用?

由於網絡分區的問題,有可能某節點無法與其他節點通信並且收不到Leader的心跳,這樣會導致該節點進行選舉,並且由於無法通信會一致不斷的增加Term編號,編號會越來越大,這樣當該節點恢復後,其他所有節點都要同步更新自己Term,並且Leader降級爲Follower節點發起選舉。整個集羣被這一個節點搞亂了。

所以採用PreVote機制,首先發起預投票,只有其他節點同意選舉後再真正發起選舉。

Raft裏面的lease(租約)機制作用?

Raft爲了防止只靠心跳機制出現雙主情況。也就是網絡分區的時候出現雙Leader節點,從而犧牲一定的可用性換一致性。
客戶端的任何讀寫請求都是通過Leader節點進行的,Leader又分爲Region Leader(邏輯上的概念)和Raft Leader,實際上請求是由Region Leader轉發給Raft Leader處理的。Region Leader和Raft Leader可能是同一個節點。

如果沒有租約機制:
比如現在由S1\S2\S3節點爲分區1,Leader爲S1。網絡分區後S4\S5節點爲分區2,老的Leader爲S4。
這時候讀請求分配到S4時造成數據不一致。
如果有租約機制:
Raft Leader選舉成功時,將自己註冊到一個節點上,由該節點作爲Region Leader,爲Raft Leader設置一個lease失效間隔,當時效過期時更新租約lease,這樣就可以避免請求轉發給老的Leader。

還以上面說的爲例,這時候客戶端的請求發到Region Leader,但是因爲網絡分區無法請求到S4節點,則lease時效後重新爲S1更新爲當前租約的Leader

參考文獻

https://zhuanlan.zhihu.com/p/32052223
https://blog.csdn.net/daaikuaichuan/article/details/98627822
https://www.jianshu.com/p/072380e12657

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