🎯 什麼情境該想到我

當你有很多節點/副本、要讓它們的狀態「最終趨於一致」,又不想靠單一協調者時。

⚙️ 怎麼用

  1. Gossip(八卦協定):每個節點週期性隨機挑幾個對象交換資訊,像謠言一樣擴散。去中心化、可擴展、對節點增減有韌性。常用於成員管理、故障偵測、狀態傳播。
  2. 反熵(Anti-Entropy):定期比對副本差異並修補,讓飄移的副本收斂。用 Merkle Tree 高效找出「哪裡不同」,只傳差異。
  3. 前景 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 的底層)或既有的資料庫機制。

🔗 相關工具