Quorum 與最終一致 (Quorum & Eventual)

★★★★Reviewed

FromDDIADatabase Internals

📚 From the Books

Quorum 與最終一致 (Quorum & Eventual)Consistency

無主複製 (leaderless) 的招牌做法:寫 w 份、讀 r 份,只要 w + r > n 讀寫副本集合就保證有交集,於是「讀至少看得到一份最新寫」。聽起來像強一致,但它既非線性一致、嚴格說連單調都不保證——它本質上是「最終一致 + 機率性的新鮮度」。

🧠 Intuition

TIP

w + r > n 只保證讀寫副本必有交集,不保證你能認出交集裡哪份才是最新值,也不保證並發/失敗中的寫入會乾淨呈現。它給的是「鴿籠原理級」的存在性保證,不是線性一致的即時性保證。

⚖️ Tradeoffs

w + r > n 給的保證 — 與它的盲點
  • 保證:讀寫副本集合相交,所以一次讀至少觸及一個含最新寫的副本。
  • 盲點 1(辨識):讀到多個版本時要靠版本號/時間戳挑最新——時鐘偏差或缺版本向量就可能挑錯。
  • 盲點 2(並發寫):兩個並發寫各達 quorum,最後是 LWW (last-write-wins) 丟資料,或留多版本要應用解衝突。
  • 盲點 3(部分失敗):寫只成功在部分副本(未達 w)卻沒回滾,後續讀可能一下看到、一下看不到。
最終一致的語意 — 「終將」有多弱
  • 唯一硬承諾:沒有新寫入時,副本最終收斂。對「多久」「過程中讀到什麼」幾乎零保證。
  • 過程中可能:讀到舊值、讀到比上次更舊的值(回退)、不同 client 看到不同順序。
  • 這些異常在低負載時罕見、易被忽略,卻會在故障 / 高延遲時集中爆發——是最危險的「看起來能用」。
Session 保證 — 把弱一致補強成「對單一使用者合理」
  • 讀己之寫 (read-your-writes):自己寫完,自己後續讀一定看得到——避免「我剛改完卻顯示沒改」。
  • 單調讀 (monotonic reads):讀到新值後不再讀回舊值——避免時光倒流。
  • 單調寫 (monotonic writes):同一 client 的寫入按序生效。
  • 這些是以單一 session 為界的保證,比全域因果弱,但能用「黏同一副本 / 帶版本戳」便宜地實作。
為何 quorum 仍非線性一致
  • 並發:兩個並發讀落在不同副本,可能一個看到新值、一個看到舊值——違反「讀到新值後全體不回退」。
  • 未完成的寫:寫入進行中(達了部分副本但未確認),交錯的讀會時新時舊,沒有單一生效瞬間。
  • 無同步讀修復:交集只保證「存在」最新副本,不保證讀操作回傳它;要近似線性一致得加同步讀修復或 quorum 讀時修復。
  • 結論:quorum 是機率性新鮮度,線性一致是確定性即時序,本質不同。

🔑 Takeaways

✍️ My Notes

2026-07-01

  • Q: 既然 w + r > n 保證交集,那把 r 拉大、讀很多副本,是不是就等於線性一致了?
  • A: 不會。交集只保證讀觸及到含最新寫的副本,但兩個並發讀可能各自落在不同的合法 quorum、看到不一致的版本;而且寫入若還在進行(部分副本完成),讀會看到時新時舊的中間態,沒有單一「生效瞬間」。要逼近線性一致,得在讀路徑加上同步讀修復(讀到舊副本就當場寫回最新),把多次讀之間的回退堵死——但那已經超出純 quorum 的範疇了。

📖 Further Reading

🔗 Dive Deeper