Raft 論文地址:https://ramcloud.atlassian.ne... 算法
Raft論文中分爲三塊:安全
本文中主要介紹領導人選舉
服務器
Raft中的節點有三種狀態:網絡
Leader
Follower
Candidate
每個節點都是一個狀態機,Raft會根據當前的心跳,任期等狀態來進行狀態的遷移轉化,就以下圖所示:併發
首先,在Raft節點啓動的時候,全部任務都是Follower
狀態, 由於此時沒有Leader
,全部Follower
都在固定的超時時間內都收不到來自Leader
的心跳,從而變成了Candidate
狀態,開始選舉Leader
spa
當節點處於Candidate
狀態的時候,會併發的向全部的節點發出請求投票請求RequestVote
(後面章節會向詳細介紹),在Candidate
狀態下,節點可能會發生三種狀態的遷移變化:.net
N/2+1
,那麼選取超時,進入下一輪選舉Leader
:若是選舉過程當中收到大於N/2+1
數量的節點的投票,那麼選舉成功,當前的節點成爲新的Leader
Follower
:若是選舉過程當中收到來及其餘節點的Leader
心跳,或者是請求投票響應的Term
大於當前的節點Term
,那麼說明有新任期的Leader
若是節點選舉成功,成爲了Leader
,那麼Leader
將會在固定週期內發送心跳到全部的節點,可是若是心跳請求收到的響應的Term
大於當前節點的Term
,那麼當前節點的就會成爲Follower
。好比Leader
節點的網絡不穩定,掉線了一段時間,網絡恢復的時候,確定有其餘節點被選爲了新的Leader
,可是當前節點在掉線的時候並無發現其餘節點選爲Leader
,仍然發送心跳給其餘節點,其餘節點就會把當前的新的Term
響應給已通過時的Leader
,從而轉變成Follower
日誌
整個集羣必需要在丟包,亂序,延時等諸多不穩定因素的狀況下,可以選舉出惟一一個Leader
code
就如上文中提到的,若是Follower
在必定時間內沒有收到心跳請求,那麼將會切換到Candidate
狀態,開始一輪新的選取,選舉過程當中會向集羣中的全部節點發送請求投票的RPCblog
RPC請求參數:
term
:當前候選人的任期號candidateId
:候選人的IdlastLogIndex
:候選人的最後日誌條目索引值lastLogTerm
:候選人的最後日誌條目的任期號其中lastLogIndex
和lastLogTerm
用來判斷候選人的日誌是否和服務器的日誌同樣新(後文中會解釋),必需要至少同樣新才能投票。
RPC響應值:
term
:被請求節點的任期號voteGranted
:是否贊成投票給候選人若是Leader
發生異常,那麼基本上全部的Follower
在同一時間切換爲Candidate
,並同時發出請求投票的RPC,那麼就有可能致使選票被均衡的瓜分,從而須要從新發起新一輪的投票。爲了不選票被瓜分的問題,選舉超時的是能夠能夠從一個固定的區間(例如150-300
毫秒)隨機選擇。
判斷當前的Term
的和請求投票參數中的Term
:
Term
> 請求投票參數中的Term
,那麼拒絕投票(設置voteGranted
爲false
),並返回當前的Term
Term
爲請求投票參數中的Term
, 並將自身狀態切換成Follower
檢測當前節點的投票狀態:
voteGranted
爲false
), 由於一個節點在一個任期內不能同時投票給多個節點檢測候選人的日誌是否至少比當前節點的日誌新,經過比較候選人的lastLogIndex
和lastLogTerm
和當前節點的日誌,確保新選舉出來的Leader
不會丟失已經提交的日誌:
votedGranted
爲true
),併成爲Follower
voteGranted
爲false
)每個候選人在每個任期內都會發出一輪投票請求,若是在指定時間內,收到大於N/2+1
個節點的贊成投票的響應,那麼說明投票成功,晉升爲Leader
由於在整個投票過程當中,假設網絡是不穩定的,那麼就有可能致使投票請求和請求的響應丟失,亂序,延時等,從而致使收到和當前任期不相匹配的響應,因此若是收到和當前任期不匹配的響應,那麼就直接丟棄不處理。
完整的處理流程以下:
檢查響應的Term
是否大於當前候選人的Term
:
Leader
被選舉出來,那麼就把當前節點從Candidate
切換爲Follower
狀態,並更新當前節點的Term
檢查響應的Term
是否和當前的節點的Term
是否相等:
檢查響應是否贊成投票:
N/2+1
,那麼就切換爲Leader
Leader
的日誌至少要比Follower
的日誌新從上文的請求投票RPC的處理流程中得知,Leader
不是隨便選一個節點均可以成爲的,若是候選人不知足要求,那麼其餘節點就不會給候選人投票。
若是集羣中的任何一個節點不通過判斷就能成爲Leader
,那麼將會發生什麼?這種狀況可能致使已經被提交的日誌被覆蓋,若是狀態機已經Apply了被覆蓋的日誌,將會致使不一致的結果。因此爲了選舉的安全性,Raft
添加了如下的限制:
Leader
不會覆蓋本身的任何日誌,Follower
嚴格按照Leader
的日誌進行復制(必要時強行覆蓋)Leader
的時候,Candidate
的日誌至少要比當前節點新(這個「新」稍後解釋),不然就拒絕投票;由於已經提交的日誌確定是存在大於等於N/2+1
個節點上的,而投票至少也須要N/2+1
個節點贊成,因此整個投票過程當中確定會有包含有全部已經提交日誌的節點存在的。上文中的「新」就是:即當前的任期和候選人的任期相同,且候選人的日誌長度比當前的日誌長度 或者 候選人的任期比比當前節點的任期高