30分鐘帶你理解 Raft 算法

爲什麼需要 Raft?

  • 要提高系統的容錯率,需要分佈式系統
  • 分佈式系統有多個實例,對於給定的一組操作,需要協議讓所有實例達成一致(分佈式一致性)
  • Paxos 是分佈式一致性協議的標準,但難以理解、實現
  • Raft 提供了和 Paxos 算法相同的功能,但更好理解、構建實際的系統

Raft 是什麼?

  • Replicated And Fault Tolerant,複製和容錯
  • 管理複製日誌的一致性算法

Raft 的目標

  • 簡單易理解
  • 提供完整的實現系統,減少開發者的工作量
  • 保證所有條件下都是安全的,在大部分情況下是可用的
  • 常用操作是高效的

前置條件:複製狀態機

  • Raft 相當於複製狀態機中的“一致性模塊
  • 一致性模塊(Consensus Module):管理來自客戶端的指令,接入 log
  • 日誌(Log)
  • 狀態機(State Machine):執行日誌的指令,得到 Server 狀態

Raft 基礎

  • 節點狀態:
    • Leader(領導者):系統只有一個節點處是 Leader,處理所有客戶端的請求並同步給 Follower
    • Follower(跟隨者):只響應其他服務器(Leader、Candidate)的請求
    • Candidate(候選者):在選舉領導的時候出現
  • term(任期):
    • 一段選舉的任期(選舉開始+正常工作)
    • term 號自動 +1
    • 如果選票均分,則該 term 直接結束,進入下一個 term
    • Raft 中的「邏輯時鐘」,可發現過期信息,規則:
      • 每個節點會存儲當前 term 號,term 編號單調遞增
      • 節點間通信,交換 term 號
      • (1)節點當前 term 號 < 他人 term 號,更新 term 號
      • (2)節點當前 term 號 > 他人 term 號,拒絕請求
      • (3)Candidate、Leader 發現自己的 term < 他人 term,立即變成 Follower
  • 節點通信:使用 RPC
    • 請求投票(RequestVote) RPCs:選舉階段,Candidate 節點發送給他人
    • 附加條目(AppendEntries)RPCs:非選舉階段,Leader 發給所有節點,複製日誌+心跳
  • 特性(Raft 保證在任何時候都成立)
    • 選舉安全:對一個給定的 term 號,最多選舉出一個 Leader
    • Leader 只附加原則:Leader 不會刪除、覆蓋自己的日誌,只會增加
    • 日誌匹配:若兩個日誌在相同索引位置的日誌的 term 號相同,則日誌從頭到該索引位置全部相同
    • Leader 完整特性:選舉出的 Leader,會包含所有已提交的日誌
    • 狀態機安全特性:Leader 已經將給定的索引值位置的日誌條目應用到狀態機,其他任何服務器都已執行

Leader 選舉(選舉安全特性)

  • Raft 使用心跳機制觸發 Leader 選舉
    • 集羣存在 Leader,Leader 節點週期性發心跳包
    • 一個 Follower 沒有收到任何消息(固定區間隨機的時間),發起選舉
  • 集羣啓動時,所有節點都處於 Follower 狀態
  • 節點到達超時時間後,會進入 Candidate 狀態,增加自己的 term 號,發送請求投票給自己
  • Candidate 狀態機
    • 節點得票最多的,變成 Leader
    • 收到來自其他節點的“聲明自己是 Leader”的請求
    • 一段時間後,沒有獲得多數票,也沒有收到其他節點的 Leader 通知(平分選票)
  • 避免選舉的平分選票:隨機選舉超時時間
    • 每個節點隨機選擇選舉超時時間,到達時間後成爲 Candidate
    • 大多數情況下,只有一個節點率先進入 Candidate

日誌複製(Leader只附加、日誌匹配)

  • Leader 會接收客戶端的請求,請求指令作爲一個“日誌條目”添加到日誌中
  • 向所有 Follower 發送附加條目 RPC,讓他們複製這個日誌條目
  • 得到大多數節點回復後,Leader 會把日誌寫入複製狀態機,持久化,把執行結果返回給客戶端
  • 日誌非安全的;進入狀態機中是安全的(已提交),最終會被所有可用的狀態機執行。

index = 7 的日誌已經被大多數節點複製,狀態爲已提交。

安全

  • 選舉限制(Leader 完整性):每次選舉出來的 Leader,必須包含所有已提交的日誌
    • 只有已經被大部分節點複製的日誌,纔會變成“已提交”
    • 一個 Candidate 必須得到大部分節點投票,才能變成 Leader
    • 投票時,節點不會把票投給沒有自己的日誌新的 Candidate
  • Follower 或 Candidate 崩潰:無限重試
  • 超時和可用性:broadcastTime(廣播時間)<< electionTimeout(選舉超時時間)<< MTBF(平均故障間隔時間)

學習資料

使用 Raft 的應用?

  • 服務發現框架:consul、etcd
  • 日誌:RocketMQ
  • 數據存儲:Tidbk8s

擴展:ZooKeeper ZAB 協議

  • 支持崩潰恢復的原子廣播協議:ZooKeeper Atomic Broadcast protocol
  • ZooKeeper 適合讀多寫少的場景,客戶端隨機連到 ZK 集羣的一個節點
    • 從當前節點讀
    • 寫入到 leader,leader 廣播事務,半數節點成功纔會被提交
  • 整體流程類似於 Raft,只是細節和實現的區別

擴展:ZooKeeper 是什麼?

官方定義: A Distributed Coordination Service for Distributed Applications。本質:基於內存的 KV 系統,以 path 爲 key

代碼、思維導圖筆記鏈接

代碼和思維導圖在 GitHub 項目中,歡迎大家 star!

coding 筆記、點滴記錄,以後的文章也會同步到公衆號(Coding Insight)中,希望大家關注_

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章