共識就是讓多個節點對某個值達成一致。聽起來簡單——幾個節點各提議、然後選一個——但在會當機、會延遲、時鐘會偏移的世界裡,這是分散式系統最難也最基礎的問題。
🧠 Core Ideas
TIP
共識不是要投票投得漂亮,而是要在部分節點故障時仍能安全地決定一個值。凡是「唯一 leader 是誰」「這筆跨節點交易到底提交還是中止」「叢集成員有哪些」,底層都是共識問題。
- 共識演算法要滿足:一致同意(不會有兩個節點決定不同值)、完整性(不決定兩次)、有效性(決定的值有人提議過)、終止性(沒當機的節點最終都會決定)。
- 前三個是 safety(任何情況都不能違反);終止性是 liveness,前提是多數節點存活且能互通。
⚖️ 為什麼共識這麼難
FLP 不可能定理
- 在確定性的非同步模型下,只要一個節點可能當機,就不存在保證總能達成共識的演算法。
- 實務解法:引入逾時偵測疑似當機的節點(等於借用了時鐘),跳出純非同步的限制——所以共識在真實系統中還是能可靠運作。
等價關係:共識 ≡ 全序廣播 ≡ 線性一致 CAS
- 全序廣播:所有節點以完全相同順序收到所有訊息——這正是狀態機複製(每個副本以相同順序套用相同輸入 → 狀態一致)的基礎。
- DDIA 的核心結論:實作線性一致的 compare-and-set、實作全序廣播、解決共識,本質是同一個問題。解出一個就解出全部。
⚖️ 容錯共識演算法(Raft / Paxos / Zab)
高層設計都長得差不多
- 投票選出一個 leader(每輪叫 term / epoch / ballot,編號單調遞增、每編號最多一個 leader)。
- Leader 提議值,其他節點投票,只有拿到 quorum(多數) 才被接受。
- 每次投票前檢查有無更高編號的 leader,有就放棄舊的。兩輪 quorum(選舉 + 提議)保證:一旦某值被決定,後續當選的 leader 都找得到它。
- Paxos(1989,難懂著稱)、Raft(2014,以「好懂」為設計目標)、Zab(ZooKeeper 用)。
與 2PC 的關鍵差異
- 2PC 要所有參與者投 yes;共識只要多數。
- 2PC 協調者是固定指派、故障就阻塞;共識 leader 由選舉產生、故障可安全選新的。
- 共識在 safety 上不做任何假設(全掛也不會決定錯),只在 liveness 上要求多數存活。
- 詳見 分散式交易。
代價與限制
- 效能:每次提議至少一輪網路往返收多數票,延遲取決於最慢的 quorum 成員(等同同步複製)。
- 選舉空窗:leader 故障到選出新 leader 期間無法寫入。
- 需嚴格多數:容忍 1 個故障要 3 節點、容忍 2 個要 5 節點;加節點不一定更快(每次決定要更多票)。
- 對網路敏感:不穩的網路會頻繁誤判 leader 故障、觸發無謂選舉,甚至 leader 在兩節點間反覆跳。
⚖️ 實務:ZooKeeper / etcd 把共識封裝成原語
少量共識、大量資料
- ZooKeeper 叢集通常只有 3~5 節點,卻協調數千個應用節點。
- 只把少量需要共識的中繼資料(誰是 leader、成員列表、工作分配)交給共識系統;大量應用資料流向不需共識的系統。
- 提供的原語:線性一致的原子 CAS(+租約做鎖)、操作全序(zxid 當 fencing token)、會話 + 心跳做故障偵測、Watch 變更通知。
- 應用少直接用它,多半透過 Kafka、HBase、YARN 等間接使用。
🔑 Takeaways
- 共識=故障下仍能安全決定一個值;leader 選舉、原子提交、成員管理都靠它。
- FLP 說純非同步下不可能,實務靠逾時繞過。
- Raft/Paxos/Zab 高層都是「選 leader → 多數投票」;比 2PC 強在只需多數、leader 可重選。
- 別自己實作共識——用 ZooKeeper / etcd,遵循「少量共識、大量資料」的分層。
No notes yet — jot your takeaways or Q&A here.