前言
Raft是一個保證分佈式系統數據一致性的共識算法,誕生的目的就是爲了探索一種更容易理解的共識算法,原因是上一個描述這個算法的協議--Paxos較難理解和在生產環境上使用。(注:筆者沒有掌握Paxos算法,所以這裏不會去作比較,後續如果學習到的話會做一個比較)
筆者主要是通過閱讀Raft論文和觀看MIT 6.824的教程視頻學習的。
論文原文是英文版的,裏面的一些專用名詞筆者打算儘量保留英文的描述,因爲這些關鍵名詞對於理解概念十分重要,但是翻譯過來會比較拗口,也找不到合適的中文名詞代替,所以打算保留英文的描述,當然,名詞的含義還是有必要先解釋一下。
英文名詞備註
Consensus algorithms:共識算法,用來保證分佈式系統一致性的方法。Consensus algorithm
leader:節點集羣中的領導者,決策者,負責複製和提交客戶端的日誌。
term:任期,領導者的當任時間。
candidate:準備參與leader選舉的候選機器
follower:追隨者,選舉結束後,沒有成爲leader的candidate就是跟隨者,接收leader的指令
majority:大多數投票機制,指集羣中大多數機器同意某個節點成爲leader,這裏的大多數機器不只是指正在運行的服務器,即使機器投票後掛了也是majority中的一部分
Raft簡介
在MIT 6.824課程視頻中,在正式討論Raft之前討論了Map Reduce、GFS、VMWare FT,而這些現存容錯系統的處理方式如下:
MapReduce系統,只是複製計算,但是依賴單master
GFS,複製副本數據,依賴master另外選主
VMware FT複製服務依賴test-and-set選擇master
單點master可以避免“腦裂”,但是master始終是單點,無法實現分佈式存儲。
腦裂,是指一個集羣中出現了網絡異常的情況導致有兩個節點各自都認爲它們都是主節點,於是一個集羣被拆分爲兩個集羣,解決腦裂問題的方式就是添加majority機制,而Paxos和Raft就是這類解決方案中的其中兩種。
由於Paxos的晦澀難懂導致難以理解以及實現起來的難度,經過不斷的掙扎,學者們就發明了Raft。Raft的目標是爲了設計一種更易於理解的共識算法。
爲了讓共識算法更容易理解,Raft將共識算法中的核心內容拆分開來實現:leader選舉,日誌複製,安全性,以及通過實施一個更強級別的一致減少需要考慮的狀態數量。
Raft跟現存的共識算法很相似,但是它有新增一些獨特的特性:
Strong Leader,比如日誌只能由首領發送到其他的服務器
Leader Election,Raft使用隨機定時器進行選舉,解決衝突時更簡單快捷
Membership changes,使用共同共識的方法來處理集羣內成員變換的問題,這種方法處理時,處於調整過程中的兩種不同配置的集羣中的大多數機器會重疊。這樣一來,集羣在成員變換階段依然能繼續運行。
複製狀態機
Replicated state machine,狀態複製機,共識算法是在複製狀態機的背景下誕生的,複製狀態機用於來解決分佈式系統的各種容錯問題。
如圖,複製狀態機實現方式是使用複製日誌,每份日誌都使用相同順序來保存相同的指令,服務器執行時是按照日誌的順序來執行,最終得到的結果都是一致的。
共識算法在複製狀態機的工作就是保證所有的複製日誌都是一致的。共識實現模塊(如Raft)接收來自客戶端的請求後,添加到機器的日誌裏,使用共識模塊進行通信,保證所有日誌最終都包含相同順序的請求。看到這裏想起了MySQL的主從複製原理,有點類似複製狀態機的實現方式。
共識算法在實際應用中的特性:
安全性保證,絕不返回一個錯誤的結果,在錯誤情況下都能保證正確
可用性,集羣中只要有大多數的機器可運行且能夠相互通信,就可以保證可用。
不依賴時序保證一致性
通常情況下,一條指令能在集羣中大多數節點響應一次遠程過程調用時完成。少部分較慢的節點不會影響系統整體的性能。
Paxos
Paxos定義了一個能夠達成單一決策共識的協議,比如單條的複製日誌項。主要的兩個缺點:
原理很難理解,完整的解釋不夠透明。
沒有提供一個較好的基礎來構建一個現實中的系統。
注:筆者沒有深入學習過Paxo,不能更多的評論,只能從論文和視頻的角度做個小總結。
初衷--更容易理解的設計
Raft有很多個設計的目標:
提供一個完整構建系統的基礎
高效性
安全性
而Raft最重要的目標,也是最大的挑戰,就是讓有一個更容易理解的設計。核心目標就是可理解性,必須是容易理解的,即使是普通開發者也能理解。
Raft的學者們意識到要達到Raft的目標非常難,所以使用了問題分解和通過減少狀態數量來達到這一目的。
問題分解也是平常開發中用到的一個很重要的技能,如需求拆解、實現細節拆解,把大問題拆解爲小問題,然後逐個擊破,最後完成目標。
在大多數情況下Raft都試圖去消除不確定性,但也有一些情況下增加一些不確定性可以提升系統的可理解性。比如,隨機化方法增加了不確定性,但通過使用相似的方法處理所有可能的選擇,有利於減少狀態空間數量。系統中使用隨機化去簡化Raft中領導選舉算法。
接下來要探索Raft的設計和實現原理,包含了數據結構和函數的定義,leader選舉、日誌複製、安全性等拆解功能的詳細設計。
Raft共識算法
Raft是一種用來管理複製日誌的共識算法。
通過選舉一個唯一的leader,Raft給予leader完整的責任去管理複製日誌來實現共識。leader會接受來自客戶端的日誌條目,複製這些條目到其他服務器,leader自己就可以決定將日誌條目放到哪臺服務器,數據流的方向只能從leader到其他服務器。
一個集羣裏有且只能有一臺leader,leader擁有最大的權利。如果某一臺leader當機了,會馬上選出下一臺leader。
如前面提到過的,Raft將整個共識算法拆分爲三個獨立的子問題:
leader選舉:當leader掛了,會選舉出新的leader
日誌複製:日誌條目只能從leader通知到集羣的其他服務器,服務器只會認leader的數據
安全性:Raft的核心安全性是狀態機的安全,Raft通過在選舉機制增加一些限制來保證提供的狀態數據都是安全的
如圖所示是Raft的數據結構和函數的定義:
圖裏是Raft算法的實現概覽,定義了一個集羣中維護的狀態以及兩個方法。方法分別是複製日誌條目和請求投票,複製日誌條目是在客戶端發送給服務端後,由leader複製到其他的follower時調用,可被用做leader的心跳包請求。請求投票時每一個leader的選舉時,candidate向其他機器返發起的請求,如果機器被選中爲leader,會馬上發一個心跳包出去,其他candidate會成爲follower,也意味着該次term的選舉結束了。
下圖列舉了Raft算法中的關鍵特性:
Raft通過以上這些特性來保證集羣裏leader選舉和日誌複製的正常運行,同時也保證了運行的安全性。
接下來繼續探索Raft的實現:包括leader選舉、日誌複製、安全性等等,全部寫完的話,涉及的篇幅較長,篇幅太長的文章會影響閱讀體驗,也較難消化,所以筆者打算另外開一篇文章繼續。
到這裏爲止,第一次的探索歷程就暫告一個段落了,筆者想留下一個在探索過程中困惑住的問題。
Q1:在leader選舉過程中,candidate是怎麼決定要投票給發起RequestVote Rpc的機器?是不是接收到請求就要投票?成爲leader有沒有什麼要求?
這個問題,會在下一次探索歷程中給出答案。如果你有任何問題,歡迎留言。
參考引用
Raft論文
https://raft.github.io/raft.pdf
MIT6.824課程視頻
https://www.bilibili.com/video/BV1R7411t71W?p=7
共識算法
https://en.wikipedia.org/wiki/Consensus_algorithm
腦裂
https://en.wikipedia.org/wiki/Split-brain_(computing)
MySQL的主從複製原理
https://www.hoohack.me/2017/07/11/learning-mysql-replication-detail
原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。
如果本文對你有幫助,麻煩順手點個贊吧,謝謝
更多精彩內容,請關注個人公衆號。