搜尋文件

輸入關鍵字,搜尋標題與正文。

    分散式系統文件 07/08

    Quorum、版本與衝突修復

    本文提要

    在沒有單一主節點的無主(Leaderless)或多主架構中,系統不再仰賴單一仲裁者判定寫入順序,而是依賴節點群體的數學交集。 然而,單靠「多數派(Quorum)」算式無法自動消除所有並行異常;版本判定、讀修復與衝突解決策略,是多副本能承諾正確讀寫的必要配套。

    18px · 寬鬆行距

    閱讀設定

    排版預覽 · 示範文字(可捲動)

    檔案與目錄

    Linux 以一棵從根目錄 / 開始的樹狀結構組織檔案。目錄用來整理檔案,也可以包含其他目錄。

    pwd
    ls -la /home
    18px

    16、18、20、22px;隨瀏覽器文字大小縮放。

    欄寬套用於背景文章;此處預覽字級與行距。手機正文自動配合螢幕。

    文件與本文目錄
    本主題文件

    在沒有單一主節點的無主(Leaderless)或多主架構中,系統不再仰賴單一仲裁者判定寫入順序,而是依賴節點群體的數學交集。 然而,單靠「多數派(Quorum)」算式無法自動消除所有並行異常;版本判定、讀修復與衝突解決策略,是多副本能承諾正確讀寫的必要配套。

    本文接續複寫、確認與故障切換,深入探討集合交集原理與衝突調解機制,為下一篇理解網路分割與 CAP 的適用邊界打下基礎。

    查證日期:2026-11-04。Quorum 與 Sloppy Quorum 依據 Amazon Dynamo 原論文(DeCandia et al.,2007);衝突分析參考分散式暫存器形式模型。未執行實際儲存叢集操作,文中集合與版本推演均為概念例子。

    Quorum 交集原理

    在擁有 $N$ 個副本的無主叢集中,客戶端直接將讀寫發送到多個節點:

    • $W$(Write Quorum):一次寫入操作必須獲得至少 $W$ 個節點的成功確認,才視為寫入成功。
    • $R$(Read Quorum):一次讀取操作必須向至少 $R$ 個節點查詢,並挑選最新版本的結果。

    根據鴿籠原理(Pigeonhole Principle),如果設定滿足: $$W + R > N$$ 則任何包含 $W$ 個節點的寫入集合,與任何包含 $R$ 個節點的讀取集合,必定至少重疊(overlap)一個節點。這意味著:讀取節點群中,必定至少有一台節點儲存了剛才成功寫入的最新資料。

    例如典型的三副本配置($N=3$):

    • 設 $W=2$、$R=2$,滿足 $2 + 2 > 3$。
    • 寫入確認了節點 ${A, B}$;後續讀取查詢了節點 ${B, C}$。
    • 節點 $B$ 是兩者的交集,讀取端因此能看見剛才的寫入。

    為什麼 $W + R > N$ 不等於線性一致

    業界常有一種誤解,認為只要設定了 $W + R > N$,系統就自然獲得了最強的線性一致性(Linearizability)。實際上,純粹的 Quorum 算式僅保證集合有交集,仍會出現以下嚴重破綻:

    1. 部分成功的寫入(Failed / Phantom Writes)

    客戶端寫入時,只成功送達 1 台節點(未達 $W=2$),其餘節點連線逾時,客戶端判定「寫入失敗」。 然而,該資料已經寫入該唯一節點。當下一個讀取請求向該節點與另一節點查詢時,因為該節點擁有較新時間戳,讀取端可能意外讀到這個「先前已宣告失敗」的值;甚至在不同讀取請求間出現「忽隱忽現」的現象。

    2. 並行寫入缺乏全序(Concurrent Overwrites)

    若兩個客戶端同時對同一物件發起寫入:Client 1 寫入 $v_1$(成功寫入 ${A, B}$);Client 2 寫入 $v_2$(成功寫入 ${B, C}$)。 兩次寫入都滿足了 $W=2$。但兩次寫入在節點 $B$ 的到達順序可能相反,且缺乏全域時鐘判定先後。讀取端即使查詢到交集節點 $B$,也無法單憑交集知道 $v_1$ 與 $v_2$ 誰才代表系統的最終意圖。

    3. 讀修復的時間差破壞單調性

    Client 1 發起讀取,向節點 ${B, C}$ 查詢,從交集節點 $B$ 讀到了最新值 $v_{new}$,但此時節點 $C$ 仍是舊值 $v_{old}$。 在線性一致性要求下,一旦 Client 1 看見 $v_{new}$,後續發起的讀取絕不能再看見 $v_{old}$。 然而,如果 Client 1 尚未完成背景修復,Client 2 隨後向節點 ${C, D}$ 讀取,可能再次看見舊值 $v_{old}$,造成全域時光倒退。

    參考 Gilbert & Lynch(2012):Perspectives on the CAP Theorem。

    版本判定與衝突解決

    為了解決交集後的版本優劣,分散式儲存發展出不同的調解機制:

    1. 最後寫入勝出(Last-Write-Wins, LWW)

    每個寫入附加實體時鐘(Wall Clock)時間戳。讀取端在多個節點回傳的值中,無條件選擇時間戳最大者,其餘舊版本被覆蓋。

    • 風險:如前篇所述,實體時鐘必然存在時鐘漂移(Clock Skew)。一台時鐘偏快的節點所寫入的錯誤資料,可能會永久覆蓋另一台時鐘偏慢節點在真實世界更晚發生的正確更新,造成安靜且不可逆的資料遺失。

    2. 版本向量(Version Vectors)

    每個物件維護一組節點計數器 $[node_1: c_1, node_2: c_2, \dots]$。

    • 當讀取端收到多個版本時,比對兩者的向量:
      • 若版本 A 的所有分量皆大於等於版本 B,則 A 在因果上嚴格覆蓋 B(A supersedes B)。
      • 若兩個版本的向量互不包含(例如 $[A:2, B:1]$ 與 $[A:1, B:2]$),系統判定兩者為並行衝突分支(Concurrent Siblings)。
    • 系統不擅自丟棄資料,而是將兩個版本同時保留,交由業務層解決(例如購物車合併,或文章匯出工作狀態標記為需人工處理)。

    背景修復與 Sloppy Quorum

    多副本系統為了維持資料最終收斂,通常搭配兩種修復機制:

    1. 讀修復(Read Repair):
      • 當讀取操作在 $R$ 個節點中發現版本不一致時(例如節點 A 是新版本,節點 B 是舊版本),協調節點在回覆客戶端的同時,非同步將新版本寫回落後的節點 B。
    2. 反熵背景同步(Anti-Entropy via Merkle Trees):
      • 節點在背景定期比對資料。為了避免全量傳輸大量數據,各節點將資料範圍計算為默克爾樹(Merkle Tree)。節點間只需比對樹根雜湊值,若不同則逐層向下比對,迅速定位出分歧的少量鍵值並進行精確同步。
    3. 寬鬆 Quorum 與暫存交接(Sloppy Quorum & Hinted Handoff):
      • Amazon Dynamo(2007)為了在網路分割或節點故障時維持極高的寫入可用性,提出 Sloppy Quorum:
      • 當原本指定的 $N$ 個副本節點中,部分節點無法連線時,寫入請求會暫時寫入非原本負責名單的健康替代節點(稱為 Hinted Handoff 節點)。
      • 替代節點會將資料妥善保存,待原目標節點恢復健康後,再將資料送回。
      • 代價:Sloppy Quorum 打破了固定集合的鴿籠原理保證。在暫存期間發起的讀取操作,若查詢原本的節點集合,將無法讀到剛才的寫入,直到資料完成交接。

    參考 DeCandia et al.(2007):Dynamo。

    理解了多數派交集的數學極限與衝突調解後,下一篇網路分割與 CAP 的適用邊界將直面網路斷開時的終極取捨:當節點群無法互相通訊時,系統如何被迫在一維性與可用性之間劃下邊界。