Raft算法的Leader选举和日志复制过程
Raft 簡介
Raft?是一種為了管理復制日志的一致性算法。它提供了和?Paxos 算法相同的功能和性能,但是它的算法結構和?Paxos 不同,使得Raft 算法更加容易理解并且更容易構建實際的系統(tǒng)。為了提升可理解性,Raft 將一致性算法分解成了幾個關鍵模塊,例如?Leader選舉、日志復制和安全性。同時它通過實施一個更強的一致性來減少需要考慮的狀態(tài)的數(shù)量。從一個用戶研究的結果可以證明,對于學生而言,Raft 算法比?Paxos 算法更加容易學習。Raft算法還包括一個新的機制來允許集群成員的動態(tài)改變,它利用重疊的大多數(shù)來保證安全性。
?
分布式一致性算法
一致性算法允許一組機器像一個整體一樣工作,即使其中一些機器出現(xiàn)故障也能夠繼續(xù)工作下去。正因如此,一致性算法在構建可信賴的大規(guī)模軟件系統(tǒng)中扮演著重要的角色。在過去的 10 年里,Paxos 算法統(tǒng)治著一致性算法這一領域:絕大多數(shù)的實現(xiàn)都是基于 Paxos 或者受其影響。同時 Paxos 也成為了教學領域里講解一致性問題時的示例。
但是不幸的是,盡管有很多工作都在嘗試降低它的復雜性,但是?Paxos 算法依然十分難以理解。并且,Paxos 自身的算法結構需要進行大幅的修改才能夠應用到實際的系統(tǒng)中。這些都導致了工業(yè)界和學術界都對?Paxos 算法感到十分頭疼。
和?Paxos 算法進行過努力之后,研究人員開始尋找一種新的一致性算法,可以為構建實際的系統(tǒng)和教學提供更好的基礎。作者的做法是不尋常的,首要目標是可理解性:是否可以在實際系統(tǒng)中定義一個一致性算法,并且能夠比?Paxos 算法以一種更加容易的方式來學習。此外,Raft 作者希望該算法方便系統(tǒng)構建者的直覺的發(fā)展。一個算法能夠工作是很重要的,而且能夠知道為什么能工作也很重要。
Raft 一致性算法就是這些工作的結果。在設計 Raft 算法的時候,使用一些特別的技巧來提升它的可理解性,包括算法分解(Raft 主要被分成了 Leader 選舉,日志復制和安全性三個模塊)和減少狀態(tài)機的狀態(tài)(相對于 Paxos,Raft 減少了非確定性和服務器互相處于非一致性的方式)。
強領導者(Strong leader):和其它一致性算法相比,Raft 使用一種更強的領導能力形式。比如,日志條目只從領導者發(fā)送給其它的服務器。這種方式簡化了對復制日志的管理并且使得 Raft 算法更加易于理解。
領導選舉(Leader election):Raft 算法使用一個隨機計時器來選舉領導者。這種方式只是在任何一致性算法都必須實現(xiàn)的心跳機制上增加了一點機制。在解決沖突的時候會更加簡單快捷。
成員關系調(diào)整(Membership changes):Raft使用一種共同一致的方法來處理集群成員變換的問題,在這種方法下,處于調(diào)整過程中的兩種不同的配置集群中大多數(shù)機器會有重疊,這就使得集群在成員變換的時候依然可以繼續(xù)工作。
實際系統(tǒng)中使用的一致性算法通常含有以下特性:
?
Leader 選舉和日志復制
Raft 的角色
Client:系統(tǒng)外部客戶端,以下?gif 使用綠色節(jié)點代表 client。
Leader:負責接受 Client 的寫請求,并將寫請求同步到所有的 Follower,使用帶有黑色實線的節(jié)點表示。
Follower:同步?Leader 的數(shù)據(jù)。
Candidate:當一定時間內(nèi)不存在 Leader 時,會有相應的 Follower 成為候選者進行 Leader 選舉,使用帶有虛線的節(jié)點表示。
?
單一節(jié)點
假設有一個單節(jié)點系統(tǒng)。以此為例,可以將這個節(jié)點視為存儲單個值的數(shù)據(jù)庫服務器。客戶端只需要將數(shù)據(jù)發(fā)送到這個服務器上就能完成存儲,讀取數(shù)據(jù)是也是從這個服務器獲取數(shù)據(jù)。一個節(jié)點只需要完好的保持數(shù)據(jù)即可,不需要共識機制,因為只有這么一個數(shù)據(jù)。但是,如果有多個節(jié)點,每個節(jié)點都需要存儲同一個值,那么就需要共識機制保證數(shù)據(jù)的一致性,即分布式共識問題。
?
單一?Leader?選舉
Raft 所有的節(jié)點都以 Follower?狀態(tài)開始。如果?Follower?沒有收到 Leader 的信息,那么它們可以成為?Candidate。然后,Candidate?從其他節(jié)點請求投票。節(jié)點將投票表決。如果?Candidate?從多數(shù)節(jié)點中獲得選票,它將成為 Leader。這個過程稱為?Leader?選舉。在 Raft 中,有兩個超時設置可控制選舉。首先是選舉超時。選舉超時是指 Follower 成為 Candidate 之前所等待的時間。選舉超時被隨機分配在 150毫秒 至 300毫秒 之間。選舉超時后,Follower?成為?Candidate?并開始新的選舉任期(Term),它先為自己投票,然后向其他節(jié)點發(fā)送請求投票的消息。如果接收節(jié)點在這個期間還沒有投票,那么它將投票給?Candidate。并且該節(jié)點重置其選舉超時。
若 Leader 宕機了,觀察選舉連任的情況。節(jié)點? A? 經(jīng)過重新選舉后成為 任期2 的 Leader。在這一個過程中獲得多數(shù)票,可以確保每個任期只能選出一位 Leader。Leader 選舉需要半數(shù)以上的 Follower 同意才行,一般節(jié)點數(shù)量應該選擇為奇數(shù)。宕機選舉如下:
Leader 開始向其 Follower?發(fā)送?"添加條目"?消息。這些消息以心跳超時指定的時間間隔發(fā)送。Follower?然后響應每個追加條目消息。此選舉任期將持續(xù)到?Follower?停止接收心跳并成為 Candidate 為止。Leader 向其他 Follower 發(fā)送 Log 同步請求時,實質(zhì)上也是一個心跳包,這里心跳包的作用:一是攜帶請求,二是刷新 Follower 的選舉超時時間。
?
多個?Candidate 競爭選舉
如果兩個節(jié)點同時成為候選節(jié)點,則可能會發(fā)生拆分表決。兩個節(jié)點都開始以相同的任期進行選舉,而每個?Candidate?都先到達一個?Follower?節(jié)點,并且得到投票?,F(xiàn)在,每位 Candidate 都有2票,并且在這個任期中將無法獲得更多選票,此時需要超時時間過后再進行選舉。節(jié)點 C 在第 5 個任期中獲得了大多數(shù)選票,因此成為 Leader。雙候選者選舉情況如下:
一個比較特殊的情況,后來者居上:
?
日志復制
系統(tǒng)的所有更改都通過 Leader。每次更改都將添加到節(jié)點的日志中。該日志條目當前未提交,因此不會更新節(jié)點的值。要提交條目,節(jié)點首先將其復制到 Follower 節(jié)點,然后 Leader 等待,直到大多數(shù)節(jié)點都寫了該條目。如下所示,該條目已提交到 Follower?節(jié)點上,并且節(jié)點狀態(tài)為?"5"。Leader 然后通知?Follower?該條目已提交?,F(xiàn)在,集群已就系統(tǒng)狀態(tài)達成共識。此過程稱為日志復制。
?
當選出一位 Leader 后,需要將系統(tǒng)的所有更改復制到所有節(jié)點(剛才是Term 0,現(xiàn)在是Term 1)。通過使用與心跳相同的?"添加條目"?消息來完成此操作。首先,客戶將更改發(fā)送給?Leader。更改將添加到 Leader 的日志中,然后將更改在下一個心跳發(fā)送給?Follower。一旦大多數(shù)?Follower?認可,便提交該條目。然后將響應發(fā)送給客戶端。現(xiàn)在,讓再發(fā)送一條命令,將值增加?"2"。最終系統(tǒng)的值更新為?"7"。
?
網(wǎng)絡分區(qū)
面對網(wǎng)絡分區(qū),Raft 仍然可以保持一致。假如添加一個分區(qū)以將[ A, B ],[ C, D, E ]分開?,F(xiàn)在有兩位 Leader 使用不同的選舉。我們添加另一個客戶端,并嘗試更新兩個 Leader。通過添加客戶端對不同分區(qū)的訪問來學習 Raft 在網(wǎng)絡分區(qū)發(fā)生時的處理策略。
分區(qū)產(chǎn)生前后:
分區(qū)產(chǎn)生后,由于[ C, D, E ]的選舉超時時間流逝,其中 C 成為候選人,向 D、E 節(jié)點發(fā)送投票請求,C 成為所在分區(qū)的 Leader。
?
分別添加客戶端訪問兩個分區(qū):
此時 客戶端 1 向 Leader B 發(fā)送請求,Leader B 會發(fā)送心跳包給 A,確認其是否可以同步,但是卻發(fā)現(xiàn)當前只有?2 個節(jié)點同意同步(包括 Leader B 自身的一票),達不到節(jié)點總數(shù)的一半以上(不到3個),所以暫時不會進行數(shù)據(jù)的更新。此時 客戶端 2?向Leader C 發(fā)送了一個請求,Leader C 把心跳包發(fā)送給 D?和 E ,收獲到半數(shù)以上節(jié)點的投票,即表明可以同步數(shù)據(jù),所以提交日志,C、D、E節(jié)點被設置為 8。
?
恢復分區(qū)后:
現(xiàn)在讓網(wǎng)絡分區(qū)恢復。節(jié)點 A、B 看到更高的選舉期限(Term)并退出。節(jié)點 A 和 B 都將回滾其未提交的條目并匹配新 Leader 的日志。現(xiàn)在,我們的日志在整個集群中是一致的。
?
總結
算法的設計通常會把正確性,效率或者簡潔作為主要的目標。盡管這些都是很有意義的目標,但是對于?Raft 而言,可理解性也是同樣的重要。一個廣為接受但是十分令人費解的算法?Paxos 已經(jīng)困擾了無數(shù)學生和開發(fā)者很多年了。在開發(fā)者把算法應用到實際的系統(tǒng)中之前,這些目標沒有被實現(xiàn),那必然會偏離發(fā)表算法時的初衷。除非開發(fā)人員對這個算法有著很深的理解并且有著直觀的感覺,否則將會對它們而言很難在實現(xiàn)的時候保持原有的期望。Raft 比?Paxos 要容易理解。Raft 也可以為實際的系統(tǒng)實現(xiàn)提供堅實的基礎。
?
?
參考:
Raft?論文:In Search of an Understandable Consensus Algorithm?(Extended Version)
Raft 算法在線演示:http://thesecretlivesofdata.com/raft/
總結
以上是生活随笔為你收集整理的Raft算法的Leader选举和日志复制过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: I/O多路复用:select、poll和
- 下一篇: 使类和成员的可访问性最小化