Raft一致性算法

全部的分佈式系統,都面臨的一個問題是多個節點之間的數據共享問題,這個和團隊協做的道理是同樣的,成員能夠分頭幹活,但老是須要共享一些必須的信息,好比誰是 leader, 都有哪些成員,依賴任務之間的順序協調等。因此分佈式系統要麼本身實現一個可靠的共享存儲來同步信息(好比 Elasticsearch ),要麼依賴一個可靠的共享存儲服務,而 Etcd 就是這樣一個服務。html

Etcd 如何實現一致性的?

說到這個就不得不提及raft協議。git

有關Raft協議和工程實現能夠參考這個連接https://raft.github.io/,裏面包含了大量的論文,視屏已經動畫演示,很是有助於理解協議。
概念與術語
leader:領導者,提供客戶提供服務(生成寫日誌)的節點,任什麼時候候raft系統中只能有一個leader。
follower:跟隨者,被動接受請求的節點,不會發送任何請求,只會響應來自leader或者candidate的請求。若是接受到客戶請求,會轉發給leader。
candidate:候選人,選舉過程當中產生,follower在超時時間內沒有收到leader的心跳或者日誌,則切換到candidate狀態,進入選舉流程。
termId:任期號,時間被劃分紅一個個任期,每次選舉後都會產生一個新的termId,一個任期內只有一個leader。termId至關於paxos的proposalId。
RequestVote:請求投票,candidate在選舉過程當中發起,收到quorum(多數派)響應後,成爲leader。
AppendEntries:附加日誌,leader發送日誌和心跳的機制
election timeout:選舉超時,若是follower在一段時間內沒有收到任何消息(追加日誌或者心跳),就是選舉超時。
Raft協議主要包括三部分,leader選舉,日誌複製和成員變動github

Raft協議的原則和特色
a.系統中有一個leader,全部的請求都交由leader處理,leader發起同步請求,當多數派響應後才返回客戶端。
b.leader歷來不修改自身的日誌,只作追加操做
c.日誌只從leader流向follower,leader中包含了全部已經提交的日誌
d.若是日誌在某個term中達成了多數派,則之後的任期中日誌必定會存在
e.若是某個節點在某個(term,index)應用了日誌,則在相同的位置,其它節點必定會應用相同的日誌。
f.不依賴各個節點物理時序保證一致性,經過邏輯遞增的term-id和log-id保證。
e.可用性:只要有大多數機器可運行並可相互通訊,就能夠保證可用,好比5節點的系統能夠容忍2節點失效。
f.容易理解:相對於Paxos協議實現邏輯清晰容易理解,而且有不少工程實現,而Paxos則難以理解,也沒有工程實現。
g.主要實現包括3部分:leader選舉,日誌複製,複製快照和成員變動;日誌類型包括:選舉投票,追加日誌(心跳),複製快照服務器

leader選舉流程
關鍵詞:隨機超時,FIFO
      服務器啓動時初始狀態都是follower,若是在超時時間內沒有收到leader發送的心跳包,則進入candidate狀態進行選舉,服務器啓動時和leader掛掉時處理同樣。爲了不選票瓜分的狀況,好比5個節點ABCDE,leader A 掛掉後,還剩4個節點,raft協議約定,每一個服務器在一個term只能投一張票,假設B,D分別有最新的日誌,且同時發起選舉投票,則可能出現B和D分別獲得2張票的狀況,若是這樣都得不到大多數確認,沒法選出leader。爲了不這種狀況發生,raft利用隨機超時機制避免選票瓜分狀況。選舉超時時間從一個固定的區間隨機選擇,因爲每一個服務器的超時時間不一樣,則leader掛掉後,超時時間最短且擁有最多日誌的follower最早開始選主,併成爲leader。一旦candidate成爲leader,就會向其餘服務器發送心跳包阻止新一輪的選舉開始。網絡

發送日誌信息:(term,candidateId,lastLogTerm,lastLogIndex)
candidate流程:
1.在超時時間內沒有收到leader的日誌(包括心跳)
2.將狀態切換爲candidate,自增currentTerm,設置超時時間
3.向全部節點廣播選舉請求,等待響應,可能會有如下三種狀況:
(1).若是收到多數派迴應,則成爲leader
(2).若是收到leader的心跳,且leader的term>=currentTerm,則本身切換爲follower狀態,
不然,保持Candidate身份
(3).若是在超時時間內沒有達成多數派,也沒有收到leader心跳,則極可能選票被瓜分,則會自增currentTerm,進行新一輪的選舉分佈式

follower流程:
1.若是term < currentTerm,說明有更新的term,返回給candidate。
2.若是尚未投票,或者candidateId的日誌(lastLogTerm,lastLogIndex)和本地日誌同樣或更新,則投票給它。
注意:一個term週期內,每一個節點最多隻能投一張票,按照先來先到原則動畫

日誌複製流程
關鍵詞:日誌連續一致性,多數派,leader日誌不變動
     leader向follower發送日誌時,會順帶鄰近的前一條日誌,follwer接收日誌時,會在相同任期號和索引位置找前一條日誌,若是存在且匹配,則接收日誌;不然拒絕,leader會減小日誌索引位置並進行重試,直到某個位置與follower達成一致。而後follower刪除索引後的全部日誌,並追加leader發送的日誌,一旦日誌追加成功,則follower和leader的全部日誌就保持一致。只有在多數派的follower都響應接受到日誌後,表示事務能夠提交,才能返回客戶端提交成功。
發送日誌信息:(term,leaderId,prevLogIndex,prevLogTerm,leaderCommitIndex)
leader流程:
1.接收到client請求,本地持久化日誌
2.將日誌發往各個節點
3.若是達成多數派,再commit,返回給client。
備註:
(1).若是傳遞給follower的lastLogIndex>=nextIndex,則從nextIndex繼續傳遞
.若是返回成功,則更新follower對應的nextIndex和matchIndex
.若是失敗,則表示follower還差更多的日誌,則遞減nextIndex,重試
(2).若是存在N>commitIndex,且多數派matchIndex[i]>=N, 且log[N].term == currentTerm,
設置commitIndex=N。spa

follower處理流程:
1.比較term號和自身的currentTerm,若是term<currentTerm,則返回false
2.若是(prevLogIndex,prevLogTerm)不存在,說明還差日誌,返回false
3.若是(prevLogIndex,prevLogTerm)與已有的日誌衝突,則以leader爲準,刪除自身的日誌
4.將leader傳過來的日誌追加到末尾
5.若是leaderCommitIndex>commitIndex,說明是新的提交位點,回放日誌,設置commitIndex =
min(leaderCommitIndex, index of last new entry).net

備註:默認狀況下,若是日誌不匹配,會按logIndex逐條往前推動,直到找到match的位置,有一個簡單的思路是,每次往前推動一個term,這樣能夠減小了網絡交互,儘快早點match的位置,代價是可能傳遞了一些多餘的日誌。日誌

快照流程
避免日誌佔滿磁盤空間,須要按期對日誌進行清理,在清理前須要作快照,這樣新加入的節點能夠經過快照+日誌恢復。
快照屬性:
1.最後一個已經提交的日誌(termId,logIndex)
2.新的快照生成後,能夠刪除以前的日誌和之前的快照。
刪日誌不能太快,不然,crash後的機器,原本能夠經過日誌恢復,若是日誌不存在,須要經過快照恢復,比較慢。

leader發送快照流程
傳遞參數(leaderTermId, lastIndex, lastTerm, offset, data[], done_flag)
1.若是發現日誌落後太遠(超過閥值),則觸發發送快照流程
備註:快照不能太頻繁,不然會致使磁盤IO壓力較大;但也須要按期作,清理非必要的日誌,緩解日誌的空間壓力,另外能夠提升follower追趕的速度。

follower接收快照流程
1.若是leaderTermId<currentTerm, 則返回
2.若是是第一個塊,建立快照
3.在指定的偏移,將數據寫入快照
4.若是不是最後一塊,等待更多的塊
5.接收完畢後,丟掉之前舊的快照
6.刪除掉不須要的日誌

日誌最終可能被覆蓋掉,好比下圖:

 

(a).S1是leader,termId是2,寫了一條日誌到S1和S2,(termId,logIndex)爲(2,2)
(b).S1 crash,S5利用S3,S4,S5當選leader,自增termId爲3,本地寫入一條日誌,(termId,logIndex)爲(3,2)
(c).S5 crash,S1 重啓後從新當選leader,自增termId爲4,將(2,2)從新複製到多數派,提交前crash
(d).S1 crash,S5利用S2,S3,S4當選leader,則將(3,2)的日誌從新複製到多數派,並提交,這樣(2,2)這條日誌曾經雖然達成多數派也會被覆蓋。
(e).假設S1在第一個任期內,將(2,2)達成多數派,則後面S3不會成爲leader,也就不會出現覆蓋的狀況。

 

參考自:

http://www.cnblogs.com/cchust/p/5634782.html

http://blog.csdn.net/cszhouwei/article/details/38374603

相關文章
相關標籤/搜索