把同一份資料放到多台機器上,目的有三個:降低延遲(資料靠近使用者)、提高可用性(節點掛了還能服務)、擴展讀取吞吐。難的從來不是複製一次,而是處理資料的變更。
🧠 Core Ideas
TIP
三種複製模型,差別在「誰能接受寫入」:單主=只有 leader 收寫、follower 收變更日誌;多主=多個節點都能收寫、彼此互相複製;無主=客戶端直接寫多個副本、靠 quorum 收斂。愈往下走,容錯愈強、一致性保證愈弱。
- Single-leader:所有寫入經 leader,讀取可在任何副本。最好理解、無寫入衝突,是關聯式資料庫(PostgreSQL、MySQL)與 Kafka 的預設。
- Multi-leader:多個節點可寫,適合多資料中心、離線客戶端、協作編輯。代價是寫入衝突要處理。
- Leaderless(Dynamo 風格):無 failover 概念,客戶端平行寫多個、平行讀多個。Dynamo、Cassandra、Riak 用這套。
⚖️ 同步 vs 非同步複製
同步 — 安全但會被慢節點卡住
- Follower 保證有與 leader 一致的最新副本,leader 掛了資料還在。
- 但同步 follower 沒回應時,寫入就得阻塞等待——任一節點故障拖垮整體。
- 實務上幾乎都是 semi-synchronous:一個 follower 同步、其餘非同步;同步的那個變慢就換人。
非同步 — 最常見,但故障會丟資料
- 即使所有 follower 落後,leader 仍可繼續寫。
- 代價:leader 故障且無法恢復時,尚未複製出去的寫入永久遺失——即使客戶端已收到成功確認。
- 讀取擴展(read-scaling)架構在非同步下效果最好,但 follower 讀到的可能是舊資料。
⚖️ 複製延遲的三種一致性問題
非同步 follower 落後時,會冒出三類具體異常,各對應一個一致性保證:
Read-after-write — 讀到自己剛寫的
- 使用者寫入後立刻讀,卻打到還沒收到該寫入的 follower,看起來像資料消失了。
- 保證:使用者一定看得到自己提交的資料。
- 做法:自己可能改過的資料(如個人檔案)從 leader 讀;或記住寫入時間戳,只讀「至少含該時間戳」的副本。跨裝置更難,需集中化的更新時間戳。
Monotonic reads — 不會時間倒流
- 連續兩次讀取先打到新 follower、再打到舊 follower,導致「先看到新的、又看到舊的」。
- 保證:看過某時間點的資料後,之後不會讀到更早的。比 strong 弱、比 eventual 強。
- 做法:讓同一使用者的讀取固定打同一個副本(如依 user ID 雜湊選副本)。
Consistent prefix reads — 因果順序不被打亂
- 觀察者看到「回答出現在問題之前」——因為問題與回答落在不同分片、複製延遲不同。
- 保證:一連串有順序的寫入,任何讀取者都以相同順序看到。
- 做法:讓有因果關係的寫入落在同一個分片。分片資料庫尤其棘手,因為各分片獨立、沒有全域寫入順序。
⚖️ 無主複製:Quorum 與衝突
w + r > n — quorum 的核心不等式
- n 個副本,寫入要 w 個確認、讀取查 r 個節點。只要 w + r > n,讀取集合必與最新寫入集合重疊,至少讀到一個新值。
- 常見 n=3, w=2, r=2。寫少讀多可設 w=n, r=1(讀更快,但一個節點掛就寫不了)。
- 邊界:sloppy quorum、並行寫、寫入部分成功等情況,即使 w+r>n 仍可能讀到舊值——所以 Dynamo 風格多半只求最終一致。
偵測並行寫入 — happens-before 與 version vector
- 「並行」不看物理時間,看是否互相知道對方:都不知道對方 → 並行。
- 單主用版本號追因果依賴;多副本無主則要每副本每 key 一組版本號= version vector(Riak 稱 causal context)。
- 合併並行值(siblings)的責任落在應用層;LWW 最簡單但會丟資料,購物車這種場景該取聯集,刪除要用 tombstone。CRDT 可自動合併。
Multi-leader 的寫入衝突
- 兩個 leader 同時改同一筆,非同步複製時才發現衝突。
- 策略:避免衝突(同一 key 固定路由到同一 leader);或收斂解決(LWW / 應用層合併 / 保留全部由使用者處理)。
- 拓撲(環形 / 星形 / 全連接)影響傳播路徑;全連接容錯較好但寫入可能亂序到達,需 version vector 排序。
🔑 Takeaways
- 複製服務於高可用、離線、低延遲、擴展四個目的;難點全在處理變更與並行。
- 面試選型先講單主 / 多主 / 無主與同步 / 非同步的取捨,再談一致性保證。
- 非同步複製的三個坑:read-after-write、monotonic reads、consistent prefix——各有對應的補救。
- 無主用 w + r > n 換可用性;但別把 quorum 當成 strong consistency。
No notes yet — jot your takeaways or Q&A here.