解讀Raft(二 選舉和日志復制)


Leader election

Raft采用心跳機制來觸發Leader選舉。Leader周期性的發送心跳(如果有正常的RPC的請求情況下可以不發心跳)包保持自己Leader的角色(避免集群中其他節點認為沒有Leader而開始選舉)。

Follower在收到Leader或者Candidate的RPC請求的情況下一直保持Follower狀態。而當一段時間內(election timeout)沒有收到請求則認為沒有Leader節點而出發選舉流程。

選舉流程如下:

  1. Follower遞增自己的任期並設置為Candidate角色
  2. 投票給自己並且並發的給所有節點發送投票請求
  3. 保持Candidate狀態直到:
    • 同一個任期內獲得大多數選票,成為Leader(一個節點在一個任期內只能給一個Candidate投票,任期相同則選票先到先得)並給其他節點發送心跳來保持自己的角色
    • 收到其他節點的RPC請求,如果請求中的任期大於等於Candidate當前的任期,認為其他節點成為了Leader,自身轉換為Follower;如果其他節點的任期小於自身的任期,拒絕RPC請求並保持Candidate角色
    • 一段時間后仍舊沒有Leader(可能是出現了平票的情況),則在選舉超時后重新發起一輪選舉(遞增任期、發送投票請求)

為了避免平票的問題,同時在出現平票的情況后能快速解決,Raft的選舉超時時間是在一個區間內隨機選擇的(150~300ms)。這樣盡量把服務器選舉時間分散到不同的時間,保證大多數情況下只有一個節點會發起選舉。在平票的情況下,每個節點也會在一個隨機時間后開始新一輪選舉,避免可能出現的一直處於平票的情況。

Log replication

一旦Leader被選舉出來后,Leader就開始為集群服務:處理所有的客戶端請求並將數據復制到所有節點。

一旦日志被“安全”的復制,那么Leader將這個日志應用到自己的狀態機並響應客戶端。

如果有節點異常或網絡異常,Leader會一直重試直到所有日志都會正確復制到所有節點(日志不允許有空洞,所以每個節點上的日志都是連續的,不能有因為失敗引起的空洞)。

日志組織形式如上圖,每個日志條目中包含可執行的指令、和日志被創建時的任期號,日志條目也包含了自己在日志中的位置,即index。一旦一個日志條目存在於大多數節點,那么該日志條目是committed的。

Raft算法保證所有committed的日志都是持久化的(日志需要在大多數節點上持久化之后再響應給客戶端,這意味着每個Follower節點收到AppendEntry請求后需要持久化到日志之后再響應給Leader),且最終會被所有的狀態機執行。

Raft算法保證了以下特性:

  • 如果兩個日志條目有相同的index和term,那么他們存儲了相同的指令(即index和term相同,那么可定是同一條指令,就是同一個日志條目)
  • 如果不同的日志中有兩個日志條目,他們的index和term相同,那么這個條目之前的所有日志都相同

兩條規則合並起來的含義:兩個日志LogA、LogB,如果LogA[i].index=Log[i]B.index且LogA[i].term=Log[i].term,那么LogA[i]=Log[i]B,且對於任何n < i的日志條目,LogA[n]=LogB[n]都成立。(這個結論顯而易見的可以從日志復制規則中推導出來)

一個新Leader被選舉出來時,Follower可能是上圖中的任何一種情況。

  • (a)(b)可能還沒復制到日志
  • (c)(d)可能曾經是Leader,所有包含了多余的日志(這些日志可能被提交了,也可能沒提交)
  • (e)可能是成為Leader之后增加了一些日志,但是在Commit之前又編程了Follower角色,且還沒有更新日志條目
  • (f)可能是在任期2稱為了Leader並追加了日志但是還沒提交就Crash了,恢復之后在任期3又成了Leader並且又追加了日志

在Raft中,通過使用Leader的日志覆蓋Follower的日志的方式來解決出現像上圖的情況(強Leader)。Leader會找到Follower和自己想通的最后一個日志條目,將該條目之后的日志全部刪除並復制Leader上的日志。詳細過程如下:

  • Leader維護了每個Follower節點下一次要接收的日志的索引,即nextIndex
  • Leader選舉成功后將所有Follower的nextIndex設置為自己的最后一個日志條目+1
  • Leader將數據推送給Follower,如果Follower驗證失敗(nextIndex不匹配),則在下一次推送日志時縮小nextIndex,直到nextIndex驗證通過

上面的方式顯然可以通過一些方法進行優化來減少重試的次數,但是在Raft論文中對是否有必要進行優化提出了質疑,因為這種異常的情況很少出現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM