分佈式系統必須知道的一個共識算法:Raft

一、Raft 概述

Raft 算法是分佈式系統開發首選的共識算法。比如現在流行 Etcd、Consul。

如果掌握了這個算法,就可以較容易地處理絕大部分場景的容錯一致性需求。比如分佈式配置系統、分佈式 NoSQL 存儲等等,輕鬆突破系統的單機限制。

Raft 算法是通過一切以領導者爲準的方式,實現一系列值的共識和各節點日誌的一致。

二、Raft 角色

2.1 角色

跟隨者(Follower)普通羣衆,默默接收和來自領導者的消息,當領導者心跳信息超時的時候,就主動站出來,推薦自己當候選人。

候選人(Candidate)候選人將向其他節點請求投票 RPC 消息,通知其他節點來投票,如果贏得了大多數投票選票,就晉升當領導者。

領導者(Leader)霸道總裁,一切以我爲準。處理寫請求、管理日誌複製和不斷地發送心跳信息,通知其他節點 “我是領導者,我還活着,你們不要” 發起新的選舉,不用找新領導來替代我。

如下圖所示,分別用三種圖代表跟隨者、候選人和領導者。

角色

三、單節點系統

3.1 數據庫服務器

現在我們想象一下,有一個單節點系統,這個節點作爲數據庫服務器,且存儲了一個值爲 X。

數據庫服務器

3.2 客戶端

左邊綠色的實心圈就是客戶端,右邊的藍色實心圈就是節點 a(Node a)。Term 代表任期,後面會講到。

客戶端

3.3 客戶端向服務器發送數據

客戶端向單節點服務器發送了一條更新操作,設置數據庫中存的值爲 8。單機環境下(單個服務器節點),客戶端從服務器拿到的值也是 8。一致性非常容易保證。

客戶端向服務器發送數據

3.4 多節點如何保證一致性?

但如果有多個服務器節點,怎麼保證一致性呢?比如有三個節點:a,b,c。如下圖所示。這三個節點組成一個數據庫集羣。客戶端對這三個節點進行更新操作,如何保證三個節點中存的值一致?這個就是分佈式一致性問題。Raft 算法就是來解決這個問題的。當然還有其他協議也可以保證,本篇只針對 Raft 算法。

在多節點集羣中,在節點故障、分區錯誤等異常情況下,Raft 算法如何保證在同一個時間,集羣中只有一個領導者呢?下面就開始講解 Raft 算法選舉領導者的過程。

四、選舉領導過程

4.1 初始狀態

初始狀態下,集羣中所有節點都是跟隨者的狀態。

如下圖所示,有三個節點 (Node) a、b、c,任期(Term)都爲 0。

初始狀態

4.2 成爲候選者

Raft 算法實現了隨機超時時間的特性,每個節點等待領導者節點心跳信息的超時時間間隔是隨機的。比如 A 節點等待超時的時間間隔 150 ms,B 節點 200 ms,C 節點 300 ms。那麼 a 先超時,最先因爲沒有等到領導者的心跳信息,發生超時。如下圖所示,三個節點的超時計時器開始運行。

超時時間

當 A 節點的超時時間到了後,A 節點成爲候選者,並增加自己的任期編號,Term 值從 0 更新爲 1,並給自己投了一票。

成爲候選者

4.3 投票

我們來看下候選者如何成爲領導者的。

Leader 選舉

4.4 任期

英文單詞是 term,領導者是有任期的。

4.5 選舉規則

4.6 大多數

假設一個集羣由 N 個節點組成,那麼大多數就是至少 N/2+1。例如:3 個節點的集羣,大多數就是 2。

4.7 心跳超時

爲了防止多個節點同時發起投票,會給每個節點分配一個隨機的選舉超時時間。這個時間內,節點不能成爲候選者,只能等到超時。比如上述例子,節點 A 先超時,先成爲了候選者。這種巧妙的設計,在大多數情況下只有一個服務器節點先發起選舉,而不是同時發起選舉,減少了因選票瓜分導致選舉失敗的情況。

成爲候選者

五、領導者故障

如果領導者節點出現故障,則會觸發新的一輪選舉。如下圖所示,領導者節點 A 發生故障,節點 B 和 節點 C 就會重新選舉 Leader。

領導者故障

總結

Raft 算法通過以下幾種方式來進行領導選舉,保證了一個任期只有一位領導,極大減少了選舉失敗的情況。

本篇通過動圖的方式來講解 Raft 算法如何選舉領導者,更容易理解和消化。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fLqQtfIVRgo6ftOuL4XBDQ