Hệ thống Dữ liệu Phân tán/Leaderless — mọi bản bình đẳng, dùng quorum
11/38
Bài 11 / 38~13 phútNhân bản (replication)Miễn phí lượt xem

Leaderless — mọi bản bình đẳng, dùng quorum

Bỏ luôn khái niệm leader: client ghi/đọc thẳng tới nhiều bản. Quorum R+W>N đảm bảo đọc thấy ghi mới nhất; read repair và anti-entropy hàn các bản lệch.

TL;DR: Leaderless (kiểu Dynamo) bỏ hẳn vai trò leader: client gửi mỗi ghi tới nhiều bản cùng lúc và coi là thành công khi W bản xác nhận; gửi mỗi đọc tới nhiều bản và lấy giá trị mới nhất trong R bản trả lời. Nếu chọn R + W vượt N (tổng số bản), tập bản đọc và tập bản ghi chắc chắn giao nhau — nên đọc luôn chạm ít nhất một bản có ghi mới nhất. Vì không có leader điều phối, các bản sẽ lệch nhau; hệ hàn lại bằng read repair (lúc đọc thấy bản cũ thì ghi đè bản mới vào) và anti-entropy (tiến trình nền so sánh và đồng bộ, thường dùng Merkle tree). Đổi lại sự đối xứng và khả dụng cao, leaderless không có thứ tự ghi toàn cục — ghi song song vẫn phải giải quyết như multi-leader (vector clock).

Single-leader có một nơi quyết thứ tự; multi-leader có vài nơi. Leaderless đi tới cực còn lại: không nơi nào đặc biệt. Client (hoặc một coordinator không-đặc-quyền) tự nói chuyện với nhiều bản và dùng số phiếu (quorum) thay cho quyền lực (leader). Đây là kiến trúc của các kho khả-dụng-cao như Dynamo/Cassandra — và là nơi mọi cơ chế bạn học ở track thuật toán phân tán hội tụ lại.

1. Analogy — hỏi nhiều người thay vì hỏi sếp

Muốn biết số liệu mới nhất, bạn có hai cách. Cách single-leader: hỏi đúng người phụ trách (leader) — chính xác nhưng nếu người đó nghỉ thì tắc. Cách leaderless: hỏi năm đồng nghiệp cùng lúc, ai cũng giữ một bản; bạn lấy câu trả lời mới nhất trong số người trả lời. Không phụ thuộc một ai — ba người bận vẫn hỏi được hai người còn lại.

Nhưng để chắc "mới nhất" là thật mới, phải có quy tắc số: khi cập nhật, bạn báo cho ít nhất ba người; khi hỏi, bạn hỏi ít nhất ba người. Vì hai nhóm ba người trong tổng năm người chắc chắn trùng ít nhất một người, người đó biết bản mới nhất — bạn không bao giờ bỏ sót. Đó chính là quorum.

Hỏi đồng nghiệpLeaderless replication
Không có "sếp" giữ bản gốcKhông có leader
Cập nhật: báo ≥3/5 ngườiGhi: W bản ack (W=3, N=5)
Hỏi: hỏi ≥3/5 ngườiĐọc: R bản trả lời (R=3)
Hai nhóm 3/5 luôn trùng ≥1R + W vượt N → giao nhau
Thấy ai giữ bản cũ thì cập nhật họRead repair
Định kỳ mọi người đối chiếu sổAnti-entropy (Merkle tree)
💡 Cách nhớ

Không hỏi sếp, hỏi số đông. R+W vượt N đảm bảo nhóm đọc và nhóm ghi luôn chạm nhau ít nhất một bản — đó là lý do quorum "thấy" được ghi mới.

2. Cơ chế quorum — R + W vượt N

Gọi N = số bản của mỗi dữ liệu. Client:

  • Ghi: gửi tới cả N bản, coi thành công khi W bản xác nhận.
  • Đọc: hỏi N bản, chờ R bản trả lời, lấy giá trị mới nhất (kèm version) trong số đó.
flowchart LR
  W["Ghi: cho W ban ack"] --> O["Tap W va tap R<br/>GIAO nhau >=1 ban"]
  R["Doc: hoi R ban"] --> O
  O --> V["Ban giao co ghi moi nhat<br/>-> doc khong bo sot"]

Nếu chọn R + W vượt N, thì tập W bản đã ghi và tập R bản đang đọc buộc phải giao nhau ít nhất một bản — bản giao đó có ghi mới nhất, nên đọc không bỏ sót.

Thử đoán trước

Có N=3 bản. Bạn muốn đọc luôn thấy ghi mới nhất. Nếu đặt W=2 (ghi cần 2 ack), thì R nhỏ nhất là bao nhiêu để đảm bảo giao nhau? Và nếu đổi sang W=1 (ghi rất nhanh), R phải bằng bao nhiêu — điều đó nói gì về đánh đổi ghi-nhanh vs đọc-nhanh?

N = 3 ban.
  W=2, R=2 -> R+W=4 > 3 -> giao nhau: doc luon thay ghi moi nhat (can bang)
  W=3, R=1 -> ghi cham (cho ca 3), doc RAT nhanh (1 ban)  -> hop doc-nhieu
  W=1, R=3 -> ghi RAT nhanh (1 ban), doc cham (ca 3)      -> hop ghi-nhieu
  W=1, R=1 -> R+W=2 < 3 -> KHONG dam bao giao -> co the doc ban cu

Quan sát: R và W là hai cần gạt để nghiêng hệ về đọc-nhanh hay ghi-nhanh, miễn giữ R+W vượt N. Đây là điểm mạnh của leaderless — chỉnh nhất quán/hiệu năng bằng tham số, không đổi kiến trúc.

3. Vì sao quorum không phải đảm bảo tuyệt đối?

Thử đoán trước

Với N=3, cấu hình cân bằng W=2, R=2 cho R+W=4 (vượt 3) nên đọc luôn thấy ghi mới. Giờ để ghi nhanh hơn, bạn hạ W=1 nhưng giữ R=2 — lúc này R+W=3, đúng bằng N. Thử đoán: một client ghi X=5 (chỉ 1 bản ack) rồi ngay sau đó client khác đọc từ 2 bản — có chắc thấy X=5 không? Vì sao mốc phải là "vượt N" chứ không phải "bằng N"?

Lần theo cơ chế: ghi X=5 chỉ chạm một trong ba bản — gọi là bản A. Lần đọc lấy hai bản bất kỳ; nếu nó trúng đúng hai bản kia (B và C, không có A), cả hai đều chưa có X=5 → client đọc phải giá trị . Với R+W đúng bằng N (ở đây 1+2=3), tập ghi (1 bản) và tập đọc (2 bản) có thể vừa khít phủ kín N mà không chồng lấn — không có bản giao. Chỉ khi R+W vượt hẳn N thì hai tập buộc phải chồng ít nhất một bản; đó là lý do công thức đòi dấu lớn hơn, không phải lớn hơn hoặc bằng.

Nhưng ngay cả khi giữ đúng R+W>N, thực tế vẫn còn kẽ hở:

  • Sloppy quorum: khi nhiều bản "đúng nhà" bị lỗi, hệ có thể chấp nhận ghi vào các bản tạm (hàng xóm) để giữ khả dụng — lúc đó W bản ack có thể không nằm trong N bản gốc, phá tính giao nhau. Ghi được lưu và chuyển về đúng nhà sau (hinted handoff), nhưng trong khoảng đó đọc có thể trượt.
  • Ghi song song: quorum đảm bảo đọc thấy các ghi, nhưng nếu hai ghi song song (không thứ tự toàn cục), quorum không tự quyết cái nào "đúng" — vẫn phải giải xung đột bằng version/vector clock (như multi-leader bài 03).
  • Ghi thất bại một phần: ghi thành công ở vài bản rồi lỗi (chưa đủ W) — một số bản đã có giá trị mới, khó rollback sạch.

Nên quorum cho xác suất cao đọc thấy ghi mới, không phải đảm bảo tuyệt đối như linearizability (Module 6). Đây là đánh đổi có chủ đích để lấy khả dụng.

4. Read repair và anti-entropy — hàn các bản lệch

Vì không leader ép đồng bộ, các bản trôi lệch (một bản bỏ lỡ ghi lúc nó đang lỗi). Hai cơ chế kéo chúng về:

  • Read repair (sửa lúc đọc): khi client đọc từ nhiều bản và thấy một bản trả về giá trị cũ hơn, nó ghi đè giá trị mới vào bản đó ngay. Sửa "thụ động" — chỉ dữ liệu được đọc mới được hàn.
  • Anti-entropy (đồng bộ nền): một tiến trình nền định kỳ so sánh các bản và chép phần thiếu — kể cả dữ liệu ít được đọc (thứ read repair bỏ sót). So sánh nguyên hai bản thì tốn; nên dùng Merkle tree để tìm nhanh chỗ khác nhau mà không truyền cả dữ liệu.
Nhớ lại Quorum R + W vượt N

Cơ chế quorum, tính giao nhau R+W>N, và đánh đổi đọc/ghi bạn đã học ở track thuật toán. Bài này là ứng dụng hệ thống của nó: leaderless replication chính là quorum áp lên dữ liệu có bản sao.

Nhớ lại Merkle tree

Anti-entropy cần so sánh hai bản dữ liệu lớn để tìm chỗ lệch mà không truyền tất cả. Merkle tree (hash cây) cho phép so từ gốc xuống, chỉ đi vào nhánh có hash khác → chi phí tỉ lệ số chỗ lệch (không quét toàn bộ), nhanh khi khác biệt ít. Đây đúng là bài toán bạn đã học; leaderless dùng nó để đồng bộ nền rẻ.

Việc phát tán thông tin thành viên/trạng thái giữa các node (ai còn sống, ai giữ khoảng khoá nào) thường dùng gossip — cũng là cơ chế bạn đã gặp ở track thuật toán.

5. Pitfall — tưởng quorum là nhất quán mạnh

Pitfall — coi R+W>N như linearizability

Sai lầm: thấy công thức R+W>N rồi kết luận "vậy leaderless luôn đọc thấy ghi mới nhất, nhất quán mạnh như một máy".

❌ Tuong: R+W>N => moi doc thay ghi moi nhat, thu tu chuan
   Thuc te:
   - sloppy quorum lay ban tam -> W ack KHONG trong N goc -> doc co the truot
   - hai ghi SONG SONG -> quorum khong quyet duoc cai nao dung -> van xung dot
   - trong luc read repair chua chay het -> hai client co the thay 2 gia tri

Hệ quả: dựa vào leaderless cho thao tác cần thứ tự tuyệt đối (ví dụ "check-and-set", đếm không trùng, khoá) → sai âm thầm, vì quorum không cung cấp linearizability.

Hướng đúng: hiểu quorum cho nhất quán cao xác suất và khả dụng tốt, KHÔNG phải nhất quán mạnh tuyệt đối. Dữ liệu chịu được đọc cũ hiếm/gộp được (đếm like, feed) hợp leaderless. Thao tác cần đảm bảo tuyệt đối (chuyển tiền, cấp khoá) cần consensus/linearizability (Module 6) — không phải quorum đọc/ghi. Chọn kiến trúc theo mức đảm bảo dữ liệu thật sự cần.

6. 📚 Deep Dive

📚 Deep Dive — Leaderless replication
  • Designing Data-Intensive Applications (Kleppmann) — Chương 5, mục "Leaderless Replication" — quorum đọc/ghi, R+W>N, giới hạn của quorum, read repair, anti-entropy, sloppy quorum + hinted handoff, phát hiện ghi song song.
  • Giuseppe DeCandia et al. (2007), "Dynamo: Amazon's Highly Available Key-value Store" — paper gốc của kiến trúc leaderless: consistent hashing để phân bản, quorum, hinted handoff, Merkle tree cho anti-entropy, version vector cho xung đột. Nhiều hệ kiểu Cassandra kế thừa thiết kế này.

Ghi chú: DDIA Ch5 và paper Dynamo là cặp nguồn chuẩn. Leaderless đánh đổi thứ tự toàn cục lấy khả dụng cao — hợp workload chịu được nhất quán yếu, không hợp thao tác cần đảm bảo tuyệt đối.

7. Liên hệ các bài khác

  • Bài 03 — Multi-leader: leaderless cũng đối mặt ghi song song và dùng chính version/vector clock để giải — cùng bài toán xung đột, kiến trúc khác (không leader).
  • Bài 02 — Replication lag: quorum R+W>N là cách giảm stale read chủ động, thay vì chỉ sống chung với lag bằng các đảm bảo session.
  • Module 3 — Phân mảnh: Dynamo dùng consistent hashing để chọn N bản cho mỗi khoá — replication và partitioning gắn chặt ở đây.
  • Module 6 — Consistency & consensus: vì sao quorum ≠ linearizability, và khi nào phải trả giá cho nhất quán mạnh.

8. Tóm tắt

  • Leaderless: không leader; ghi tới nhiều bản (thành công khi W ack), đọc từ nhiều bản (lấy mới nhất trong R).
  • Quorum R+W>N: tập ghi và tập đọc chắc chắn giao nhau → đọc chạm ít nhất một bản có ghi mới nhất. R, W là hai cần gạt nghiêng đọc-nhanh vs ghi-nhanh.
  • Quorum là nhất quán cao xác suất, không tuyệt đối: sloppy quorum, ghi song song, ghi lỗi một phần đều tạo kẽ hở.
  • Read repair (sửa lúc đọc) + anti-entropy (đồng bộ nền, Merkle tree) hàn các bản lệch; gossip phát tán trạng thái thành viên.
  • Không có thứ tự ghi toàn cục → ghi song song vẫn xung đột, giải bằng version/vector clock (như bài 03).
  • Anti-pattern: coi R+W>N là linearizability → dùng cho check-and-set/khoá → sai âm thầm. Thao tác cần đảm bảo tuyệt đối thuộc về consensus (Module 6).

9. Tự kiểm tra

Tự kiểm tra
Q1
Giải thích vì sao R + W > N đảm bảo một lần đọc thấy được ghi mới nhất. Với N=3, W=2, R nhỏ nhất là bao nhiêu?

Ghi thành công khi W bản đã lưu giá trị mới; đọc hỏi R bản. Nếu R + W > N, hai tập này (cỡ W và cỡ R trong tổng N) không thể rời nhau — buộc giao ít nhất một bản. Bản giao đó nằm trong W bản đã ghi nên có giá trị mới nhất (kèm version), và vì nằm trong R bản đang đọc nên client thấy nó → không bỏ sót ghi mới.

Với N=3, W=2: cần R + 2 > 3 → R ≥ 2. Vậy R nhỏ nhất là 2 (R+W=4 vượt 3). R=1 (R+W=3) không vượt N nên có thể trượt.

Q2
W=1,R=3 và W=3,R=1 (với N=3) khác nhau thế nào về hiệu năng đọc/ghi? Mỗi cấu hình hợp workload nào?

Cả hai đều có R+W=4 vượt N=3 nên đảm bảo giao nhau. Khác ở chi phí đặt vào đâu:

  • W=1, R=3: ghi chỉ cần 1 bản ack → ghi rất nhanh; đọc phải chờ cả 3 → đọc chậm. Hợp workload ghi-nhiều.
  • W=3, R=1: ghi chờ cả 3 → ghi chậm; đọc chỉ 1 bản → đọc rất nhanh. Hợp workload đọc-nhiều.

R và W là hai cần gạt để nghiêng hệ về đọc-nhanh hay ghi-nhanh mà không đổi kiến trúc — miễn giữ R+W vượt N.

Q3
Vì sao quorum R+W>N là 'nhất quán cao xác suất' chứ không phải đảm bảo tuyệt đối? Nêu ít nhất hai kẽ hở.

Vì trong lỗi/đồng thời, tính giao nhau bị phá:

  • Sloppy quorum: khi nhiều bản gốc lỗi, hệ nhận ghi vào bản tạm (hàng xóm) để giữ khả dụng → W ack có thể không nằm trong N bản gốc → đọc từ N gốc có thể trượt cho tới khi hinted handoff chuyển về.
  • Ghi song song: quorum đảm bảo đọc thấy các ghi, nhưng không quyết được cái nào "đúng" khi hai ghi song song — vẫn cần version/vector clock.
  • Ghi lỗi một phần: ghi thành công ở vài bản rồi lỗi (chưa đủ W) → vài bản đã có giá trị mới, khó rollback sạch.

Nên quorum cho xác suất cao thấy ghi mới + khả dụng tốt, không phải linearizability.

Q4
Phân biệt read repair và anti-entropy. Vì sao chỉ read repair là không đủ, và Merkle tree giúp gì cho anti-entropy?

Read repair sửa lúc đọc: khi client thấy một bản trả giá trị cũ, nó ghi đè giá trị mới vào bản đó — nhưng chỉ dữ liệu được đọc mới được hàn.

Anti-entropy là tiến trình nền đối chiếu các bản và chép phần thiếu, kể cả dữ liệu ít được đọc — thứ read repair bỏ sót (nếu chỉ dựa read repair, dữ liệu lạnh có thể lệch mãi và mất khi bản còn-đúng chết).

Merkle tree (hash cây) giúp anti-entropy so sánh hai bản lớn mà không truyền tất cả: so hash từ gốc xuống, chỉ đi vào nhánh có hash khác nhau → chi phí tỉ lệ số chỗ lệch (không quét toàn bộ), tiết kiệm băng thông.

Q5
Vì sao dùng leaderless cho một thao tác 'check-and-set' (ví dụ cấp một khoá duy nhất) là sai? Nó cần gì thay thế?

Vì check-and-set cần thứ tự tuyệt đối: "kiểm tra khoá chưa ai giữ rồi mới set" phải là một bước không ai chen ngang. Quorum R+W>N chỉ đảm bảo đọc thấy ghi mới với xác suất cao, không cung cấp thứ tự toàn cục: hai client có thể cùng đọc "khoá trống" (qua quorum) rồi cùng set — cả hai tưởng mình thắng (ghi song song), và quorum không tự phân xử.

Thao tác này cần linearizability/consensus (Module 6) — một cơ chế đảm bảo mọi node đồng ý một thứ tự duy nhất cho các thao tác. Đó là lý do các hệ dùng leaderless cho dữ liệu chịu nhất quán yếu, nhưng dùng consensus (etcd/ZooKeeper) cho khoá/bầu leader.

Bài tiếp theo: Chọn mô hình replication theo workload

Bài này có giúp bạn hiểu bản chất không?

Hỏi đáp về bài này

Chưa có câu hỏi

Đặt câu hỏi

Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).

Đặt câu hỏi đầu tiên