Raft 算法是解決分布式系統一致性問題的,與 Paxos 實現的功能相同,相對來說更容易實現和理解。這些一致性協議可以保證在集群中大部分節點(半數以上節點)可用的情況下,集群依然可以工作並給出一個正確的結果。
Raft 將一致性問題分解為多個子模塊解決:
- Leader 選舉 Leader election
- 日誌同步 log replication
- 安全性 safety
- 日誌壓縮 log compaction
- 成員變更 membership change
Raft 將系統中的角色分為:
- Leader 接受客戶端請求,並且向 Follower 同步請求日誌,當日誌同步到大多數節點上後告訴 Follower 提交日誌。
- Follower 接受並持久化 Leader 同步的日誌,在 Leader 通知可以提交後提交日誌。
- Candidate 是選舉過程中的臨時角色。
Raft 要求系統在任何一個時刻最多只有一個 Leader,正常工作期間只有 Leader 和 Follower。
Raft 算法角色狀態轉換如下:
Follower 只響應其它伺服器的請求,如果 Flower 超時沒有接受到 Leader 的消息,它會成為一個 Candidate 狀態並開始一次 Leader 選舉,收到大多數伺服器投票的 Candidate 會成為新的 Leader,Leader 在宕機之前會一直保持 Leader 狀態。
Raft 算法將時間分為一個個的任期 term,每一個 term 的開始都是 Leader 選舉,在成功選舉 Leader 之後,Leader 會在整個 term 內管理整個集群,如果 Leader 選舉失敗,這個 term 就會因為沒有 Leader 而結束。
Leader 選舉(Leader election)
Raft 使用心跳觸發 Leader 選舉。當伺服器啟動時,初始化為 Follower。Leader 向所有 Follower 周期性發送 heartbeat。如果 Follower 選舉超時,會等待一段隨機時間後再發起一次 Leader選舉。選舉出 Leader 後,會定期向所有 Follower 發送 heartbeat 維持狀態,如果 Follower 一段時間沒有收到心跳則認為 Leader 已經掛了,再次發起Leader選舉過程。
日誌複製 (log replication)
Leader 選舉出來後,就開始接收客戶端的請求,把日誌條目加入到日誌處理中,然後並行的向其它伺服器發起請求複製日誌條目。當這條日誌被複製到大多數伺服器中,Leader會把這條日誌狀態改變向客戶端返回執行結果。
如果某個Follower沒有複製成功,則Leader會無限的重試直到Follower最終存儲了所有的日誌條目。日誌由有序編號和日誌條目組成,每條日誌條目包含它被創建時的任期號 term,和用於狀態機執行的命令。
安全性 (safety)
Raft增加兩條極限值來保證安全性:
- 擁有最新已提交的log entry 的 Follower 才有資格成為 Leader
- Leader只能推進commit index 來提交當前term的已經複製到大多數節點上的日誌,舊的term日誌會跟隨當前term的日誌來間接提交。
日誌壓縮 (log compaction)
通過定期記錄 snapshot 來解決,每個副本獨立的對自己系統狀態進行snapshot,並且是已提交的日誌進行。snapshot 包含日誌元數據,最後一條已提交的 log entry 的 log index 和 term。Leader會發送snapshot給最後日誌太多的Follower,或者新加入的機器。
copy-on-write https://blog.csdn.net/u012501054/article/details/90241124
做一次snapshot可能耗時過長,會影響正常日誌同步。可以通過使用copy-on-write技術避免snapshot過程影響正常日誌同步。
成員變更 (membership change)
不同節點之間同步成員變更存在間隙,會導致一致性問題。Raft提出兩階段成員變更方法,集群從舊成員配置切換過度成員配置,叫做共同一致,是指舊成員配置和新成員配置組合,一旦共同一致被提交,系統再切換到新成員配置。
Raft與Multi-Paxos的不同: