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)中,希望大家關注_


免責聲明!

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



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