一致性算法 - Raft協議流程詳解


-     引文    -java

我們上文總體的介紹了下Raft協議,Raft協議分區容忍的一致性協議的核心思想:一致性的保證不必定非要全部節點都保持一致,只要大多數節點更新了,對於整個分佈式系統來講數據也是一致性的。Raft 協議將概念分解成:Leader election、Log replication、Safety。Raft 把一致性協議劃分爲 Leader 選舉、MemberShip 變動、日誌複製、Snapshot 等幾個幾乎徹底解耦的模塊,實現了模塊化設計。git

Raft 設計原則是經過減小狀態數量將狀態空間簡化:github

  • 日誌不容許出現空洞 , 而且 Raft限制了日誌不一致的可能性
  • 使用隨機化時鐘簡化了領導選舉的算法

-     領袖選舉    -web

Raft協議爲了保證Leader的健壯性,使用瞭如下技術保證選舉的簡單化實現:算法

  • 超時驅動:Heartbeat/Election timeout
    安全

  • 隨機的超時時間:下降選舉碰撞致使選票被瓜分的機率服務器

Raft協議爲了保證選舉投票的有效性,規定了一系列的投票原則:
微信

  • 在任一任期內,單個節點最多隻能投一票
  • 候選人知道的信息不能比本身的少優先:投票節點經過對比Term(任期)和CommitId來判斷是否投「贊成」票。
  • first-come-first-served 先來先得 :收到多個RequestVote RPC拉票,對首先到達的進行投票

Raft 總體選舉流程以下:
架構

  • Candidate發起投票時將自身當前任期加1(NewTerm),並向集羣中全部節點發起投票請求(RequestVote RPC:請求中包含新的任期值);app

  • follower節點 根據投票原則進行 投票
  • Candidate獲得大於半數節點的「贊成」後成爲Leader,與其餘節點創建心跳,並更新全部節點的當前任期爲NewTerm;
  • 若是不夠半數,則選舉失敗,啓用隨機選舉超時策略
    • 全部 Condidate 隨機sleep (即timeout)一段時間,而後開始新一輪的選舉。
    • 第一個甦醒 Condidate 會向全部 Condidate 發出投票給個人申請
    • 尚未甦醒的 Condidate 就只能投票給已經甦醒的 Condidate 。


-     日誌複製    -

Raft 協議定義的日誌格式以下:

(TermId, LogIndex, LogValue)其中 (TermId, LogIndex) 能肯定惟一一條日誌

Raft 協議 複製策略規定一系列的原則:

  • 連續性:日誌不容許出現空洞
  • 有效性:
    • 一個log被複制到大多數節點,就是committed,保證不會回滾
    • leader必定包含最新的committed log,所以leader只會追加日誌,不會刪除覆蓋日誌
    • leader只能提交當前term的日誌;不能提交前任日誌
    • 當出現了leader與follower不一致的狀況,leader強制follower複製本身的log

Followers 日誌有效性檢查:

  • AppendEntries RPC中還會攜帶前一條日誌的惟一標識(prevTermId, prevLogIndex)
  • 遞歸推導

Followers 日誌恢復:

  • Leader 將 nextIndex 遞減並重發 AppendEntries,直到與 leader 日誌一致

Raft協議的日誌複製完整流程以下:

  • leader 將client的請求命令做爲一條新的日誌項寫入日誌。
  • leader 發送AppendEntries RPC 給follower 備份 該日誌項。
  • follower收到leader的AppendEntries RPC,將該日誌項記錄到日誌並反饋ack。
  • leader 收到 半數以上的follower 的ack,即認爲消息發送成功
  • leader 將 該日誌項 提交狀態機(state machine)處理
  • leader 將執行結果返回給 client
  • leader 發送AppendEntries RPC 通知 follower 提交狀態機
  • follower 收到AppendEntries RPC,follower判斷該日誌項是否已執行,若未執行則執行commitIndex以及以前的日誌項。


-     安全性   -

Radt協議經過一系列的規範定義,保證了整個Raft機制的數據的順序一致性。總體原則以下

  • 選舉限制
    • 用投票規則的限制來組織日誌不全的服務器贏得選舉
      • RequestVote RPC限制規則: 拒絕日誌沒本身新的candidate
    • 領袖節點只能追加日誌,不能重寫或者刪除日誌
    • 日誌條目只能從leader流向follower
  • 如何提交上一個任期的日誌條目
    • 全程保持本身的任期號
  • 安全性論證
    • 領導人完整性原則(Leader Completeness)
      • 某指令在某個任期中存儲成功,則保證存在於領袖該任期以後的記錄中。
      • 不一樣節點,某位置上日誌相同,那麼該位置以前的全部日誌必定是相同的。
    • 狀態機安全原則(State Machine Safety)
      • 若是節點將某一位置的日誌應用到了狀態機,那麼其餘節點在同一位置不能應用不一樣的日誌

經過上述的規範定義,咱們能夠經過一些異常場景來突出Raft協議的安全性:

  • 追隨者死機

當某臺追隨者死機時,全部給它的轉發指令和拉票的消息都會因沒有迴應而失敗,此時發送端會持續重送。當這臺追隨者引導從新加入集羣,就會收到這些消息,追隨者會從新迴應,若是轉發的指令已經寫入,不會重複寫入。

  • 領袖死機

領袖死機或斷線時,每一個已存儲指令一定已經寫入到過半的服務器中,此時選舉流程會讓記錄最完整的服務器勝選。其中一個因素是Raft候選人拉票時會揭露本身記錄最新一筆的信息,若是服務器本身的記錄比較新,就不會投票給候選人。

  • 超時期限和可用性

由於Raft引導選舉是基於超時,使得超時期限的選擇至爲關鍵。若遵照算法的時限需求:廣播時間 << 超時期限 << 平均故障間隔。這三個時間定義以下:

    • 廣播時間:單一服務器發送消息給集羣中每臺服務器並獲得迴應的平均時間,須要測量獲得。
    • 超時期限:發動選舉的超時期限,由部署Raft集羣的人選定。
    • 平均故障間隔:服務器發生故障之間的平均時間,能夠測量或估計獲得。

廣播時間典型是 0.5ms 到 20ms,平均故障間隔一般是用周或月來計算的,因此能夠將超時期限設在 10ms 到 500ms。


-     總結   -

本文整體介紹了Raft協議的三個核心概念及對應流程規範,經過這三個概念流程咱們能夠很容易理解和實現Raft協議。Raft以容易理解著稱,業界也涌現出不少 raft 實現,好比大名鼎鼎的 etcd, braft, tikv 等。也有不少知名的獨立的Raft協議開源框架:

lhttps://github.com/sofastack/sofa-jraft/ 源於螞蟻,java編寫

lhttps://github.com/hashicorp/raft 源於hashicorp,go編寫

lhttps://github.com/baidu/braft 源於百度,C++編寫

lhttps://github.com/rabbitmq/ra 源於rabbitmq,Erlang編寫


-     做者介紹    -

林淮川

畢業於西安交通大學;奈學教育《百萬架構師訓練營》講師、企業級源碼內源負責人,前大樹金融高級架構師、技術委員會開創者、技術總監;前天陽宏業交易事業部技術主管;多年互聯網金融行業(ToB)經驗。



本文分享自微信公衆號 - 川聊架構(gh_44ec4115d261)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索