Raft協(xié)議

Raft概述

Raft 是工程上使用較為廣泛的 強(qiáng)一致性、去中心化娩脾、高可用 的分布式協(xié)議赵誓,用于管理副本復(fù)制(Log Replication)。相比傳統(tǒng)的 Paxos 算法柿赊,Raft 將大量的計(jì)算問題分解成為了一些簡(jiǎn)單的相對(duì)獨(dú)立的子問題俩功,并有著和 Multi-Paxos 同樣的性能。

Raft的首要目標(biāo)就是容易理解(Understandable)碰声。

Raft相對(duì)來說易于實(shí)現(xiàn)主要?dú)w結(jié)為以下幾個(gè)原因:

  • 問題分解(模塊化):把一致性協(xié)議劃分為 Leader 選舉诡蜓、MemberShip 變更、日志復(fù)制胰挑、SnapShot 等相對(duì)比較解耦的模塊蔓罚;
  • 設(shè)計(jì)簡(jiǎn)化(狀態(tài)簡(jiǎn)化):比如不允許類似 Paxos 算法的亂序提交、使用 Randomization 算法設(shè)計(jì) Leader Election 算法以簡(jiǎn)化系統(tǒng)的狀態(tài)洽腺,只有 Leader脚粟、Follower、Candidate 等等蘸朋。

Raft相比Paxos有很多相似之處核无,但是有這么幾個(gè)新特性:

  • Strong leader:使用strong leader可以簡(jiǎn)化管理。例如log entries只從leader流向其他server.
  • Leader election:使用randomized timer來簡(jiǎn)化選舉過程藕坯。相比其他共識(shí)算法增加了heartbeat機(jī)制
  • Membership changes:Raft變更服務(wù)器集群的使用了一種新的方法团南,保證了服務(wù)器的配置變更也能繼續(xù)運(yùn)行。

概念

角色

Raft中節(jié)點(diǎn)存在三種狀態(tài)炼彪,節(jié)點(diǎn)會(huì)根據(jù)集群的狀態(tài)轉(zhuǎn)變自己的狀態(tài):

  • Leader:Leader 會(huì)一直工作吐根,直到失敗。Leader 節(jié)點(diǎn)負(fù)責(zé)處理所有客戶端的請(qǐng)求辐马,定期向集群中的 Follower 節(jié)點(diǎn)發(fā)送心跳消息拷橘,證明自己還健在。
  • Follower:Follower 只響應(yīng)來自其他服務(wù)器的請(qǐng)求。Follower 節(jié)點(diǎn)不處理 Client 的請(qǐng)求冗疮,而是將請(qǐng)求重定向給集群的 Leader 節(jié)點(diǎn)萄唇,由 Leader 節(jié)點(diǎn)進(jìn)行請(qǐng)求處理。
  • Candidate:如果 Follower 長(zhǎng)時(shí)間沒有收到任何通信术幔,它將成為 Candidate 并發(fā)起選舉另萤。獲得多數(shù)選票的 Candidate 成為新的 Leader。

選舉

  • Leader Election(領(lǐng)導(dǎo)人選舉):簡(jiǎn)稱選舉诅挑,就是從候選人中選出領(lǐng)袖四敞;
  • Term(任期):它其實(shí)是個(gè)單獨(dú)遞增的連續(xù)數(shù)字,每一次任期就會(huì)重新發(fā)起一次領(lǐng)導(dǎo)人選舉拔妥;
  • Election Timeout(選舉超時(shí)):就是一個(gè)超時(shí)時(shí)間忿危,當(dāng)群眾超時(shí)未收到領(lǐng)袖的心跳時(shí),會(huì)重新進(jìn)行選舉毒嫡。

角色變化

相比Paxos復(fù)雜的角色劃分癌蚁,Raft算法只有三種角色分類:Follower、Candidate和Leader兜畸。所有的Server都會(huì)在這三種角色中相互轉(zhuǎn)換努释,轉(zhuǎn)換流程如下:

Raft-Node

初始狀態(tài),所有節(jié)點(diǎn)都是群眾

  • 群眾->候選人:定時(shí)器先過期咬摇,選舉開始
  • 候選人->領(lǐng)導(dǎo)者:獲得大多數(shù)投票
  • 候選人->群眾:發(fā)現(xiàn)已經(jīng)有領(lǐng)導(dǎo)者或者更新的任期
  • 候選人->候選人:定時(shí)器超時(shí)或者進(jìn)入一輪新的任期
  • 領(lǐng)導(dǎo)者->群眾:發(fā)現(xiàn)有節(jié)點(diǎn)有更高的任期

系統(tǒng)中最多只有一個(gè)Leader伐蒂,如果在一段時(shí)間里發(fā)現(xiàn)沒有Leader,則大家通過選舉-投票選出Leader肛鹏。Leader會(huì)不停的給follower發(fā)心跳消息逸邦,表明自己的存活狀態(tài)。如果Leader故障在扰,那么follower會(huì)轉(zhuǎn)換成candidate缕减,重新選出Leader。

  1. 所有節(jié)點(diǎn)啟動(dòng)時(shí)都是follower狀態(tài)芒珠;
  2. 在一段時(shí)間內(nèi)如果沒有收到來自leader的心跳桥狡,從follower切換到candidate,發(fā)起選舉;
  3. 如果收到過半票(含自己的一票)則切換到leader狀態(tài)皱卓;如果發(fā)現(xiàn)其他節(jié)點(diǎn)日志比自己更新裹芝,則主動(dòng)切換到follower。

工作流程

數(shù)據(jù)的流向只能從 Leader 節(jié)點(diǎn)向 Follower 節(jié)點(diǎn)轉(zhuǎn)移娜汁。當(dāng) Client 向集群 Leader 節(jié)點(diǎn)提交數(shù)據(jù)后嫂易,Leader 節(jié)點(diǎn)接收到的數(shù)據(jù)處于未提交狀態(tài)(Uncommitted),接著 Leader 節(jié)點(diǎn)會(huì)并發(fā)向所有 Follower 節(jié)點(diǎn)復(fù)制數(shù)據(jù)并等待接收響應(yīng)掐禁,確保至少集群中超過半數(shù)節(jié)點(diǎn)已接收到數(shù)據(jù)后再向 Client 確認(rèn)數(shù)據(jù)已接收怜械。一旦向 Client 發(fā)出數(shù)據(jù)接收 Ack 響應(yīng)后颅和,表明此時(shí)數(shù)據(jù)狀態(tài)進(jìn)入已提交(Committed),Leader 節(jié)點(diǎn)再向 Follower 節(jié)點(diǎn)發(fā)通知告知該數(shù)據(jù)狀態(tài)變成了已提交缕允。

從這里看出這個(gè)Leader 的作用是相當(dāng)大的融虽,事實(shí)也確實(shí)如此。Raft 協(xié)議強(qiáng)依賴 Leader 節(jié)點(diǎn)的可用性來確保集群數(shù)據(jù)的一致性灼芭。

在這個(gè)過程中,主節(jié)點(diǎn)可能在任意階段掛掉般又, Raft 協(xié)議針對(duì)不同階段也有保障數(shù)據(jù)一致性的解決方案彼绷。

1 數(shù)據(jù)到達(dá) Leader 節(jié)點(diǎn),但未復(fù)制到 Follower 節(jié)點(diǎn)

這個(gè)階段 Leader 掛掉茴迁,數(shù)據(jù)屬于未提交狀態(tài)寄悯,Client 不會(huì)收到 Ack 會(huì)認(rèn)為超時(shí)失敗可安全發(fā)起重試。Follower 節(jié)點(diǎn)上沒有該數(shù)據(jù)堕义,重新選出新的主謀后可再次接收客戶端的請(qǐng)求猜旬。原來的 Leader 節(jié)點(diǎn)恢復(fù)后作為 Follower 加入集群重新從當(dāng)前任期的新 Leader 處同步數(shù)據(jù),強(qiáng)制保持和 Leader 數(shù)據(jù)一致倦卖。

2 數(shù)據(jù)到達(dá) Leader 節(jié)點(diǎn)洒擦,部分follower拿到復(fù)制的數(shù)據(jù),但還未向 Leader 響應(yīng)接收

這個(gè)階段 Leader 掛掉怕膛,數(shù)據(jù)在 Follower 節(jié)點(diǎn)處于未提交狀態(tài)(Uncommitted)且不一致熟嫩,Raft 協(xié)議要求投票只能投給擁有最新數(shù)據(jù)的節(jié)點(diǎn)。所以擁有最新數(shù)據(jù)的節(jié)點(diǎn)會(huì)被選為 Leader 再?gòu)?qiáng)制同步數(shù)據(jù)到 Follower褐捻,數(shù)據(jù)不會(huì)丟失并最終一致掸茅。

3 數(shù)據(jù)到達(dá) Leader 節(jié)點(diǎn),所有follower拿到復(fù)制的數(shù)據(jù)柠逞,但還未向 Leader 響應(yīng)接收

這個(gè)階段 Leader 掛掉昧狮,雖然數(shù)據(jù)在 Follower 節(jié)點(diǎn)處于未提交狀態(tài)(Uncommitted)但保持一致,重新選出 Leader 后可完成數(shù)據(jù)提交板壮,此時(shí) Client 由于不知到底提交成功沒有逗鸣,可重試提交。針對(duì)這種情況 Raft 要求 RPC 請(qǐng)求實(shí)現(xiàn)冪等性个束,也就是要實(shí)現(xiàn)內(nèi)部去重機(jī)制慕购。

4 數(shù)據(jù)到達(dá) Leader 節(jié)點(diǎn),成功復(fù)制到 Follower 所有或多數(shù)節(jié)點(diǎn)茬底,數(shù)據(jù)在 Leader 處于已提交狀態(tài)沪悲,但在 Follower 處于未提交狀態(tài)

這個(gè)階段 Leader 掛掉,重新選出新 Leader 后的處理流程和階段 3 一樣阱表。

5 數(shù)據(jù)到達(dá) Leader 節(jié)點(diǎn)殿如,成功復(fù)制到 Follower 所有或多數(shù)節(jié)點(diǎn)贡珊,數(shù)據(jù)在所有節(jié)點(diǎn)都處于已提交狀態(tài),但還未響應(yīng) Client

這個(gè)階段 Leader 掛掉涉馁,Cluster 內(nèi)部數(shù)據(jù)其實(shí)已經(jīng)是一致的门岔,Client 重復(fù)重試基于冪等策略對(duì)一致性無影響。

Raft協(xié)議關(guān)鍵點(diǎn)

選舉啟動(dòng)條件

Follower在Election timeout內(nèi)沒有收到來自leader的心跳烤送,(也許此時(shí)還沒有選出leader寒随,大家都在等;也許Leader炸了帮坚;也許只是leader與該follower之間網(wǎng)線被老鼠咬斷了)妻往,則會(huì)主動(dòng)發(fā)起選舉。

步驟

  1. 增加節(jié)點(diǎn)本地的 current term 试和,切換到candidate狀態(tài)
  2. 投自己一票
  3. 并行給其他節(jié)點(diǎn)發(fā)送 RequestVote RPCs
  4. 等待其他節(jié)點(diǎn)的回復(fù)

出現(xiàn)結(jié)果

  1. 收到majority的投票(含自己的一票)讯泣,則贏得選舉,成為leader
  2. 被告知?jiǎng)e人已當(dāng)選阅悍,那么自行切換到follower
  3. 一段時(shí)間內(nèi)沒有收到majority投票好渠,則保持candidate狀態(tài),重新發(fā)出選舉

投票限制

  1. 在任一任期內(nèi)节视,單個(gè)節(jié)點(diǎn)最多只能投一票
  2. 候選人知道的信息不能比自己的少
  3. first-come-first-served 先來先得


    Raft-Node-ABC.png

若有三個(gè)節(jié)點(diǎn)A B C(上圖)拳锚。A B同時(shí)發(fā)起選舉,而A的選舉消息先到達(dá)C肴茄,C給A投了一票晌畅,當(dāng)B的消息到達(dá)C時(shí),已經(jīng)不能滿足上面提到的第一個(gè)約束寡痰,即C不會(huì)給B投票抗楔,而A和B顯然都不會(huì)給對(duì)方投票。A勝出之后拦坠,會(huì)給B,C發(fā)心跳消息连躏,節(jié)點(diǎn)B發(fā)現(xiàn)節(jié)點(diǎn)A的term不低于自己的term,知道有已經(jīng)有Leader了贞滨,于是轉(zhuǎn)換成follower入热。

Raft-Node-ABCD.png

若沒有任何節(jié)點(diǎn)獲得過半投票,比如上圖晓铆。則等待超時(shí)勺良,引入randomized election timeouts奇數(shù)個(gè)節(jié)點(diǎn)避免

Log replication

共識(shí)算法基于Replicated state machines來實(shí)現(xiàn),即相同的初識(shí)狀態(tài) + 相同的輸入 = 相同的結(jié)束狀態(tài)骄噪。

Leader將客戶端請(qǐng)求(command)封裝到一個(gè)個(gè)log entry糖赔,將這些log entries復(fù)制(replicate)到所有follower節(jié)點(diǎn)佛猛,然后大家按相同順序應(yīng)用(apply)log entry中的command,則最終狀態(tài)肯定是一致的允蜈。

請(qǐng)求完整流程

  1. leader append log entry
  2. leader issue AppendEntries RPC in parallel
  3. leader wait for majority response
  4. leader apply entry to state machine
  5. leader reply to client
  6. leader notify follower apply log

由于是遠(yuǎn)程請(qǐng)求宴咧,各個(gè)節(jié)點(diǎn)的操作都經(jīng)過RPC實(shí)現(xiàn)

Log matching

每個(gè)log entry不僅包含client的command還包含log entry的leader term,每個(gè)節(jié)點(diǎn)不要求完全一致,只求最終一致。未達(dá)到最終一致的時(shí)候掌实,leader會(huì)不斷嘗試給follower發(fā)log entry,直到完全一致邦马。

由于server的連接可能出現(xiàn)問題贱鼻,每個(gè)server的log entries都有可能不同,根據(jù)不同的情況可以進(jìn)行分類做log matching:

  • 出現(xiàn)follower的log index比master少或者term比當(dāng)前term小滋将,則進(jìn)行額外的log commit
  • log index大于當(dāng)前index或者term高于當(dāng)前l(fā)og entries的忱嘹,進(jìn)行l(wèi)og刪除
  • log term小于或者不同于當(dāng)前的term的,進(jìn)行l(wèi)og覆蓋

Safety

Raft通過上面幾個(gè)屬性保障在各類異常情況下仍然正常工作(數(shù)據(jù)中心被炸不算)

Log Compaction

由于Log只執(zhí)行追加操作耕渴,而不進(jìn)行刪除和覆蓋,Raft需要定期執(zhí)行l(wèi)og compaction齿兔。snapshot可以分以下情況以提升性能橱脸。

  • 定期做日志 snapshot,可使用copy-on-write技術(shù)
  • 可以直接保留最新的log index和term
  • Leader執(zhí)行AppendEntries RPC時(shí)分苇,節(jié)點(diǎn)log entry落后太多也可以直接發(fā)送snapshot

總結(jié)

Raft 主要包括兩個(gè)獨(dú)立的子問題添诉,Leader election和log replication。流程就是先選舉出Leader医寿,然后由Leader負(fù)責(zé)復(fù)制和提交log栏赴。
為了保證算法的safety屬性,Raft對(duì)其子問題加上了諸多約束:

Election restriction:

  • 每個(gè)任期的節(jié)點(diǎn)在進(jìn)行投票都只能投一票靖秩,原則是先來先到
  • 選舉人的信息必須比自己了解的多(term, log replication)

Log replication

  • 一個(gè)log可以被復(fù)制到大多數(shù)節(jié)點(diǎn)(committed)须眷,且不能被回滾;
  • Leader 一定包含最新的committed log,因此log只會(huì)追加而不會(huì)覆蓋刪除沟突;
  • 不同節(jié)點(diǎn)花颗,某個(gè)位置上日志相同,那么這個(gè)位置之前的所有日志一定是相同的惠拭;
  • Raft 不能夠提交上個(gè)任期的log entries扩劝。

參考:

  1. Raft動(dòng)畫
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市职辅,隨后出現(xiàn)的幾起案子棒呛,更是在濱河造成了極大的恐慌,老刑警劉巖域携,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件簇秒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡涵亏,警方通過查閱死者的電腦和手機(jī)宰睡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門蒲凶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拆内,你說我怎么就攤上這事旋圆。” “怎么了麸恍?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵灵巧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我抹沪,道長(zhǎng)刻肄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任融欧,我火速辦了婚禮敏弃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘噪馏。我一直安慰自己麦到,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布欠肾。 她就那樣靜靜地躺著瓶颠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刺桃。 梳的紋絲不亂的頭發(fā)上粹淋,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音瑟慈,去河邊找鬼桃移。 笑死,一個(gè)胖子當(dāng)著我的面吹牛葛碧,可吹牛的內(nèi)容都是我干的谴轮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼吹埠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼第步!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缘琅,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤粘都,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后刷袍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翩隧,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年呻纹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堆生。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片专缠。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖淑仆,靈堂內(nèi)的尸體忽然破棺而出涝婉,到底是詐尸還是另有隱情,我是刑警寧澤蔗怠,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布墩弯,位于F島的核電站,受9級(jí)特大地震影響寞射,放射性物質(zhì)發(fā)生泄漏渔工。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一桥温、第九天 我趴在偏房一處隱蔽的房頂上張望引矩。 院中可真熱鬧,春花似錦侵浸、人聲如沸脓魏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至混蔼,卻和暖如春履腋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惭嚣。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工遵湖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晚吞。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓延旧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親槽地。 傳聞我的和親對(duì)象是個(gè)殘疾皇子迁沫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容