初次實作 Raft 的筆記

機器翻譯 原文.


我用 Python 實作了 Raft 共識演算法(分散式演算法的代表)。 這個實作相當糟糕! 不過也(算是)正確。

以下是一些筆記,想分享給其他有興趣接受類似挑戰的人。


回頭來看,以下是學習 Raft 並正確實作時最有用的資源。

我建議先花一小時左右閱讀論文,接著為 UDP 或 TCP 伺服器寫一些程式骨架,讓它能讀取傳入的位元組,並將這些位元組加入陣列。 之後我跟著 Eli 的實作,按相同的順序為自己的 Raft 實作加入功能。

在做出看起來能正常運作的選舉機制之後,我便開始尋找程式錯誤,以及自己對演算法理解上的錯誤。 我會反覆對照學生指南、Raft 論文中的圖 2,以及自己的實作,仔細思考我的實作在哪些地方相同(或不同)。 我也大量使用 LLM 來審查這份程式碼,並把上述資源的內容加入上下文。

針對日誌複寫、持久化等功能,重複上述流程。


關於實作

我在實作時做了一些簡化設計的選擇。 以下順序不分先後:

  1. 每個節點都在單一執行緒上運作並處理訊息
  2. 使用「邏輯時鐘」來追蹤系統上的本地「時間」(例如,呼叫 tick() 並遞增各節點自己的計數器,而非使用系統時間)
  3. 把所有東西都放在同一個檔案裡,讓實作變得「混雜」,例如網路資料解析、儲存/持久化、Raft 核心演算法,以及控制節點本身的工具/命令

第 2 點看來是健全且正確的設計選擇(etcd 的實作用的就是邏輯時鐘)。 第 3 點對學習/教學來說,可以說更好。 把所有東西都放在同一個檔案裡很方便,因為你能一次看到全貌,也能得到一份可以拆開重整的實作,試試哪些抽象方式最適合這個演算法。

第 1 點對我來說就有點離譜了。 這確實讓實作簡單許多(你比較不用擔心死結,以及節點內部狀態更新的原子性),但最後做出來的東西也就不完全是 Raft 了。 以第一次實作來說,這樣似乎沒問題。 演算法本身已經夠複雜了,我想你應該會更願意把時間花在修正 Raft 核心演算法中的邏輯錯誤上,而不是為互斥鎖傷腦筋。


我認為以這種方式實作 Raft,是一個約需 30 小時的專案。 一開始閱讀 Raft 論文和研讀相關資料,應該會花上幾個小時。 假期期間,我花了約 3 天完成大部分的程式撰寫,每天埋頭寫程式約 6-8 小時。 我目前的實作還有一些地方需要修整和改進(例如修正一些不易察覺的錯誤),可能還要再花半天的時間。

總的來說,能藉此理解支撐著 這麼多 基礎設施的核心演算法之一,還算不錯。