🎯 什麼情境該想到我
當你有很多節點/副本、要讓它們的狀態「最終趨於一致」,又不想靠單一協調者時。
⚙️ 怎麼用
- Gossip(八卦協定):每個節點週期性隨機挑幾個對象交換資訊,像謠言一樣擴散。去中心化、可擴展、對節點增減有韌性。常用於成員管理、故障偵測、狀態傳播。
- 反熵(Anti-Entropy):定期比對副本差異並修補,讓飄移的副本收斂。用 Merkle Tree 高效找出「哪裡不同」,只傳差異。
- 前景 vs 背景修復:讀取時順手修(read repair)+ 背景反熵掃描,兩者互補。
適合「最終一致」的大規模系統(Cassandra、DynamoDB 風格)。
★ Gossip 為什麼可擴展: 輪就傳遍
每輪:每個已知的節點隨機挑 k 個對象傳播
★ 感染的節點數是指數成長的(像流行病模型)
N = 10,000 節點、k = 3
→ 約 log₃(10000) ≈ 9 輪就幾乎全部收到
→ ★ 每個節點每輪只發 3 則訊息,不是 9999 則
| 中心化廣播 | ★ Gossip | |
|---|---|---|
| 訊息數 | (中心發給所有人) | ★ 每節點 ,與 N 無關 |
| 單點故障 | ★ 有(中心掛了就停) | ❌ 沒有 |
| 收斂速度 | 1 輪 | 輪 |
| 節點增減 | 要更新中心的名單 | ★ 自動適應 |
★ 代價是「最終」而非「立即」,而且沒有完成的通知——
你永遠不知道「大家都收到了」,只知道機率上應該收到了。
★ 三種 Gossip 模式(用途不同)
| 模式 | 做什麼 | 適合 |
|---|---|---|
| Push | 「我有新資訊,給你」 | 更新少時快 |
| Pull | 「你有什麼我沒有的?」 | ★ 更新多時效率高 |
| ★ Push-Pull | 兩者都做 | 實務標配,收斂最快 |
★ 反熵與 Merkle Tree:怎麼「只傳差異」
問題:兩個副本各有 1000 萬筆資料,要找出哪幾筆不一樣。逐筆比對要傳 1000 萬個雜湊。
Merkle Tree 的做法:
root hash ← ★ 先只比這一個
/ \
h(AB) h(CD) ← 不同才往下比
/ \ / \
h(A) h(B) h(C) h(D)
| | | |
資料A 資料B 資料C 資料D
① 比 root:相同 → ★ 整棵樹一致,比對結束(傳 1 個雜湊)
② 不同 → 比兩個子節點 → 只往「不同」的那邊下降
③ 走到葉節點 → 就是有差異的那幾筆
★ 比對成本 O(log n),傳輸量 ∝ 差異的數量,不是資料總量
★ 這是「用樹狀雜湊做高效差異比對」的通用技巧,不只用在資料庫:
Git 的物件模型、區塊鏈的交易驗證、IPFS、rsync 都是同一個思路。
★ 兩種修復路徑(互補,都要)
| 路徑 | 時機 | 特點 |
|---|---|---|
| ★ 讀修復(read repair) | 讀取時發現副本不一致,順手修 | ✅ 免費(搭在讀取上) ❌ ★ 沒人讀的資料永遠不會被修 |
| ★ 反熵(anti-entropy) | 背景定期掃描 | ✅ 涵蓋冷資料 ❌ 有 I/O 成本,要限速 |
★ 只做讀修復的系統,冷資料會無限期地飄移——這就是為什麼 Cassandra 一定要排 nodetool repair。
提示修復(hinted handoff):寫入時目標節點暫時不可用 → 協調者先暫存,等它回來再補送。
★ 但提示會過期(max_hint_window),超過就只能靠反熵。
★ 「最終」到底是多久
這是最實用的一個問題,而答案是:取決於你有沒有排修復。
| 情況 | 收斂時間 |
|---|---|
| 正常運作(gossip + 讀修復) | 毫秒~秒 |
| 節點短暫離線 + 提示修復 | 回來後幾分鐘 |
| ★ 節點離線超過 hint window | ★ 直到下一次反熵掃描——可能是幾天 |
| ★ 沒排反熵、資料也沒人讀 | ★ 永遠不收斂 |
★ 「最終一致」不是自動發生的,是被維運出來的。
這是實務上最容易被忽略的一點——它需要排程、需要監控、需要資源預算。
Gossip 的其他用途
| 用途 | 例子 |
|---|---|
| 成員管理 | 誰在叢集裡(Cassandra、Consul、Serf) |
| 故障偵測 | 傳播「誰可疑」(見 工具-故障偵測) |
| 設定傳播 | 拓撲、schema 版本 |
| ★ CRDT 同步 | 配合 CRDT 可保證無論傳播順序如何都收斂 |
🧪 我實際套用的紀錄
- 2026-07-15:(待填)
⚠️ 注意 / 什麼時候不適用
- ★ 需要立即一致就不能用 gossip。選主、唯一性約束、扣庫存要共識(見 工具-線性一致性與共識)。
- ★ 反熵一定要限速。全量 Merkle 比對 + 修復是重度 I/O,不限速會把生產叢集拖垮。
Cassandra 的 repair 造成線上事故是很常見的。排在離峰時間、限制並行度。 - ★ 修復要排程,不能只靠讀修復(見上)。而且要監控上次成功修復的時間。
- 墓碑(tombstone)與修復的交互:刪除的資料若在
gc_grace_seconds內沒完成修復,
★ 已刪除的資料會「復活」(某個節點沒收到刪除,反過來把它傳播回去)。
這是 Cassandra 最惡名昭彰的坑。 - Gossip 有流量成本。節點數很多時,光是 gossip 本身就是可觀的頻寬。
- Merkle Tree 的建立成本不低(要掃過所有資料算雜湊),所以不能太頻繁。
- 不要自己實作。用
hashicorp/memberlist(Serf/Consul 的底層)或既有的資料庫機制。
🔗 相關工具
- 工具-故障偵測 —— gossip 最常見的用途之一
- 工具-資料複製 —— 無主複製與讀修復
- 工具-線性一致性與共識 —— 需要強保證時的對照
- 工具-一致性雜湊 —— 副本放在哪些節點
- 工具-儲存引擎B-Tree與LSM-Tree —— 墓碑的來源
- 雜湊表 —— Merkle Tree 的基礎
- 設計資料密集型應用