前言
我們之前講述了 Paxos 一致性算法,雖然樓主嘗試用最簡單的算法來闡述,但仍然還是有點繞。樓主最初懷疑自己太笨,后來才直到,該算法的晦澀難懂不是只有我一個人這么認為,而是國際公認!
所以 Paxos 算法在 1990 就發表出來,但卻得不到運用。真正的名聲大噪還是在蘭伯特使用 “更簡單” 的方式重寫了一篇論文才開始。
這些和今天說的 Raft 有什么關系呢?
答:Raft 也是一個一致性算法,和 Paxos 目標相同。但他還有另一個名字:易於理解的一致性算法。
也就是說,他的目標就是成為一個易於理解的一致性算法。以替代 Paxos 的晦澀難懂。
那我們就開始講講 Raft 算法吧!
1. 什么是 Raft 算法
首先說什么是 Raft 算法:Raft 是一種為了管理復制日志的一致性算法。
什么是一致性呢?
Raft 的論文這么說的:一致性算法允許一組機器像一個整體一樣工作,即使其中一些機器出現故障也能夠繼續工作下去。
這里的一致性
針對分布式系統。
什么是管理日志呢?
一致性算法是從復制狀態機的背景下提出的,復制狀態機通常都是基於復制日志
實現的,這個日志可以理解為一個比喻,相當於一個指令。
關於狀態機的描述:
多個節點上,從相同的初始狀態開始,執行相同的一串命令,產生相同的最終狀態。實際上,與其說是一致,其實可以泛化為分布式的兩個節點狀態存在某種約束。
復制狀態機通常都是基於復制日志實現的,保證復制日志相同就是一致性算法的工作了。
典型應用就是一個獨立的的復制狀態機去管理領導選舉和存儲配置信息並且在領導人宕機的情況下也要存活下來。比如 Chubby 和 ZooKeeper。
對於 Raft 更重要的應該是 易於理解
。從 Raft 的論文題目就可以看出:In Search of an Understandable Consensus Algorithm (Extended Version)
。這里的易於理解是相對於 Paxos 的,在他的論文中,和 Paxos 做了大量針對 易於理解
的對比和統計測試。
從樓主閱讀論文的過程中來看,Raft 相較於 Paxos 確實更易於理解。為了提升可理解性,Raft 將一致性算法分解成了幾個關鍵模塊,例如領導人選舉、日志復制和安全性。
而和一致性最相關的就是前面 2 個模塊:領導人選舉和日志復制。
2. 領導人選舉
Raft 通過選舉一個高貴的領導人,然后給予他全部的管理復制日志的責任來實現一致性。
而每個 server 都可能會在 3 個身份之間切換:
- 領導者
- 候選者
- 跟隨者
而影響他們身份變化的則是 選舉
。
當所有服務器初始化的時候,都是 跟隨者
,這個時候需要一個 領導者
,所有人都變成 候選者
,直到有人成功當選 領導者
。
角色輪換如下圖:
而領導者也有宕機的時候,宕機后引發新的 選舉
,所以,整個集群在選舉和正常運行之間切換,具體如下圖:
從上圖可以看出,選舉和正常運行之間切換,但請注意, 上圖中的 term 3 有一個地方,后面沒有跟着 正常運行
階段,為什么呢?
答:當一次選舉失敗(比如正巧每個人都投了自己),就執行一次 加時賽
,每個 Server 會在一個隨機的時間里重新投票,這樣就能保證不沖突了。所以,當 term 3 選舉失敗,等了幾十毫秒,執行 term 4 選舉,並成功選舉出領導人。
接着,領導者周期性的向所有跟隨者發送心跳包來維持自己的權威。如果一個跟隨者在一段時間里沒有接收到任何消息,也就是選舉超時,那么他就會認為系統中沒有可用的領導者,並且發起選舉以選出新的領導者。
要開始一次選舉過程,跟隨者先要增加自己的當前任期號並且轉換到候選人狀態。然后請求其他服務器為自己投票
。那么會產生 3 種結果:
a. 自己成功當選
b. 其他的服務器成為領導者
c. 僵住,沒有任何一個人成為領導者
注意:
- 每一個 server 最多在一個任期內投出一張選票(有任期號約束),先到先得。
- 要求最多只能有一個人贏得選票。
- 一旦成功,立即成為領導人,然后廣播所有服務器停止投票阻止新得領導產生。
僵住怎么辦? Raft 通過使用隨機選舉超時時間(例如 150 - 300 毫秒)的方法將服務器打散投票。每個候選人在僵住的時候會隨機從一個時間開始重新選舉。
以上,就是 Raft 所有關於領導選舉的策略。
3. 日志復制
一旦一個領導人被選舉出來,他就開始為客戶端提供服務。
客戶端發送日志給領導者,隨后領導者將日志復制到其他的服務器。如果跟隨者故障,領導者將會嘗試重試。直到所有的跟隨者都成功存儲了所有日志。
下圖表示了當一個客戶端發送一個日志給領導者,隨后領導者復制給跟隨者的整個過程。
4 個步驟:
- 客戶端提交
- 復制數據到所有跟隨者
- 跟隨者回復
確認收到
- 領導者回復客戶端和所有跟隨者
確認提交
。
可以看到,直到第四步驟,整個事務才會達成。中間任何一個步驟發生故障,都不會影響日志一致性。
4. 總結
總結一下本文吧:
Raft 算法如同他的論文名字一樣:尋找一種易於理解的一致性算法
,這里的 易於理解
是相對於 Paxos 的,的確,Paxos 實在過於復雜了。
而如何實現易於理解?
答:Raft 將一致性算法分成了2部分:領導選舉,日志復制。
領導選舉基於一個隨機的時間來保證不會沖突(如果沖突的話)。
而日志復制則類似於 2PC。
通常 5 個節點,只要不超過 2 個節點死亡都不會影響系統的運行。保證了系統的可用性,通過領導者的日志復制,實現了系統的一致性。
似乎 CAP 定理已經不起作用了,當然這又是一個重大的話題。
最后,以 Raft 論文的結尾結束本位:
算法的設計通常會把正確性,效率或者簡潔作為主要的目標。盡管這些都是很有意義的目標,但是我們相信,可理解性也是一樣的重要。在開發者把算法應用到實際的系統中之前,這些目標沒有一個會被實現,這些都會必然的偏離發表時的形式。除非開發人員對這個算法有着很深的理解並且有着直觀的感覺,否則將會對他們而言很難在實現的時候保持原有期望的特性。
引用
尋找一種易於理解的一致性算法(擴展版)Raft 中文翻譯
Raft 英文原文
Raft 為什么是更易理解的分布式一致性算法