共識是分佈式容錯系統的基礎問題,是指多個服務器對值達成一致。
raft 設計目的:
- 易於理解
- 跟 Paxos 有同等容錯能力和性能
raft 服務器狀態:
- 領導(leader):處理所有客戶端請求
- 跟隨者(follower):被動響應候選人和領導
- 候選人(candidate):中間狀態,在選舉時出現
領導選舉(Leader election)
terms(任期)
- 所有的服務器管理着當前任期:
- 任期單調遞增
- 作爲邏輯時鐘管理
- 無論服務器在何時進行通信,任期會進行交換
- 任期交換規則:
- 當 A 的任期大於 B 的任期時,B 更新任期爲 A 的
- 當 A 的任期大但 B 認爲自己纔是領導時,B 迴歸跟隨者狀態
- 當 A 的任期大但收到來自 B 的請求時,A 拒絕 B 的請求,B 更新任期後再發出請求
跟隨者狀態
- 所有服務器都是從跟隨者狀態開始
- 所有服務器都有本地的計時器
- 只要在計時內能收到來自領導或候選人的消息(心跳消息),就一直保持跟隨者狀態
- 當計時內未收到心跳消息,則認爲系統沒有存活的(viable)領導,開始選舉流程,自提名(nominate)爲候選人
如何解決多個跟隨者自提名爲候選人的問題?各個服務器使用隨機的計時超時
候選人狀態
- 跟隨者進入後續人狀態過程:增加當前任期,並設置狀態爲候選人
- 給自己投一票,然後再發送投票請求到其他服務器
- 其他服務器收到投票請求後,會增加任期,然後投票
- 候選人計票,當得到大多數選票後,轉爲領導狀態,併發送心跳消息;若落選,退出到跟隨者狀態。
日誌複製(Log replication)
日誌:
- 每個節點都維護着一份操作日誌(action log)
- 日誌中的每一條目(entry)包括:操作和任期(action and term),任期表示節點接收到操作的時間。
複製過程:
- 當客戶端請求進入領導節點時(rd<-Ready),領導節點先追加條目到自身的日誌中(storage append rd.Entrieds)
- 接下來,領導節點告知其他節點追加條目,並等待確認追加( transport send rd.Messages)
- 正如選舉過程,複製過程也是遵循少數服從多數的原則,當收到大多數節點的確認時,領導會提交條目(commit entry),然後更新狀態機,再回覆成功消息給客戶端和其他節點。(applyConfChange & advance)
如果跟隨者失敗了,領導會不斷嘗試去追加,一旦跟隨者復活,條目會被最終提交。
如果領導失敗了,那麼條目將不會被提交,進入下個任期選舉,併產生新的條目。
etcd-raft
etcd/raft 中的心跳和選舉週期都是通過邏輯時鐘控制的,一般設置心跳週期爲1 個邏輯時鐘,選舉週期爲 10 個邏輯時鐘。接入 etcd/raft 時,需要自定義一個 Ticker,然後在 tick 之後,以心跳爲例,內部會將 heartbeatElapsed 自增,然後判斷是否到達設定的 Timeout,到達則恢復 heartbeatElapsed 爲 0,並執行心跳操作。
參考
https://db.cs.duke.edu/courses/compsci512/spring15/lectures/raft-guest.pptx