Chọn mô hình replication theo workload
Single-leader, multi-leader hay leaderless? Không có cái tốt nhất — chỉ có cái hợp workload. Khung quyết định theo nơi ghi, độ trễ, chịu phân tách và mức nhất quán cần.
TL;DR: Ba mô hình replication không xếp hạng "tốt hơn/kém hơn" — mỗi cái thắng ở một vùng workload. Single-leader đơn giản, không xung đột ghi, nhất quán dễ suy luận — mặc định tốt cho phần lớn hệ; giá là leader thành nút thắt ghi và điểm căng lúc failover. Multi-leader cho ghi độ trễ thấp ở nhiều nơi và hoạt động khi phân tách (đa datacenter, offline, cộng tác) — giá là write conflict phải giải quyết. Leaderless cho khả dụng cao và chỉnh nhất quán bằng quorum R/W — giá là không thứ tự toàn cục, nhất quán chỉ ở mức xác suất. Chọn bằng cách hỏi ba câu: ghi có cần ở nhiều nơi độc lập, kể cả khi mạng phân tách, không? chịu được đọc cũ tới đâu? có thao tác cần đảm bảo tuyệt đối không? Câu trả lời dẫn thẳng tới mô hình — và nhiều hệ thật dùng nhiều mô hình cho các loại dữ liệu khác nhau.
Bốn bài trước mổ từng mô hình. Bài này là bài tổng hợp: đặt chúng cạnh nhau và cho bạn một khung để chọn. Không có câu trả lời thuộc lòng — có một quy trình hỏi đúng câu.
1. Analogy — chọn phương tiện theo chuyến đi
Không có phương tiện "tốt nhất" để đi lại — chỉ có cái hợp chuyến đi. Đi gần, gọn nhẹ thì đi bộ/xe máy là nhanh nhất và khỏi lo gì; đi xa nhiều điểm, cần linh hoạt đổi chặng thì tự lái xe riêng; còn khi cần luôn tới nơi dù tuyến này tắc hay hãng kia ngừng chạy, phải trông vào cả một mạng lưới nhiều tuyến (đường nào cũng được, miễn đủ chỗ) chứ không dựa vào một cách đi duy nhất. Chọn ngược chiều thì lố bịch hoặc bất khả: tự lái xe riêng ra đầu ngõ, hay đi bộ xuyên mấy tỉnh. Bạn quyết theo quãng đường, hành lý, mức gấp — không theo "phương tiện nào oách nhất".
Chọn mô hình replication y hệt: quyết theo đặc tính workload — ghi ở đâu, chịu đọc cũ tới đâu, cần đảm bảo gì — không theo "kiến trúc nào nghe hiện đại nhất".
| Chọn phương tiện | Chọn replication |
|---|---|
| Đi gần, gọn nhẹ → đi bộ/xe máy | Ghi một nơi, cần đơn giản → single-leader |
| Đi xa nhiều điểm, linh hoạt từng chặng → xe riêng | Ghi nhiều nơi độc lập (đa DC/offline) → multi-leader |
| Cần luôn đi được, chịu đổi tuyến/chờ → mạng lưới nhiều tuyến | Cần khả dụng cao, chịu nhất quán yếu → leaderless |
| Quyết theo quãng đường & hành lý | Quyết theo workload: nơi ghi, mức chịu đọc cũ |
| "Phương tiện oách nhất" | "Kiến trúc hiện đại nhất" (bẫy chọn sai) |
Đừng hỏi "cái nào tốt nhất", hỏi "chuyến đi của mình cần gì". Bắt đầu từ ràng buộc dữ liệu rồi để nó chọn mô hình — hệt như để quãng đường chọn phương tiện.
2. Ba mô hình cạnh nhau
| Tiêu chí | Single-leader | Multi-leader | Leaderless |
|---|---|---|---|
| Nơi nhận ghi | Một leader | Nhiều leader | Bất kỳ bản (qua quorum) |
| Write conflict | Không (một nơi quyết thứ tự) | Có → phải giải | Có (ghi song song) → phải giải |
| Ghi khi mạng phân tách | Không (mất leader = tắc ghi) | Có (mỗi phía ghi tiếp) | Có (đủ quorum là ghi được) |
| Độ trễ ghi | Có thể cao (bay tới leader) | Thấp (leader gần) | Thấp (đủ W bản gần) |
| Nhất quán đọc | Mạnh nếu đọc leader; lag ở follower | Yếu (lag + conflict) | Chỉnh bằng R/W, xác suất cao |
| Độ phức tạp | Thấp | Cao (conflict) | Cao (quorum, repair, version) |
| Hợp nhất với | Phần lớn app, dữ liệu quan hệ | Đa datacenter, offline, cộng tác | Khả dụng cao, chịu nhất quán yếu |
Đọc bảng theo tinh thần Module 1: mỗi cột là một bộ đánh đổi giữa reliability, độ trễ, nhất quán và độ phức tạp — không có cột nào thắng mọi hàng.
3. Chọn mô hình bằng ba câu hỏi nào?
Thay vì nhớ "dùng cái nào khi nào", hỏi ba câu theo thứ tự:
flowchart TB
Q1{"Ghi can o NHIEU noi<br/>doc lap (da DC/offline)?"}
Q1 -->|"Khong"| Q2{"Can kha dung RAT cao,<br/>chiu doc cu hiem?"}
Q1 -->|"Co"| ML["Multi-leader<br/>(giai conflict)"]
Q2 -->|"Khong"| SL["Single-leader<br/>(mac dinh)"]
Q2 -->|"Co"| LL["Leaderless<br/>(quorum R/W)"]
SL --> Q3{"Co thao tac can<br/>DAM BAO tuyet doi?"}
LL --> Q3
ML --> Q3
Q3 -->|"Co"| CC["Tach rieng: dung consensus<br/>(Module 6) cho phan do"]- Ghi có cần ở nhiều nơi độc lập không? (đa datacenter cần ghi cục bộ, client offline, cộng tác thời gian thực) → nếu có, gần như buộc multi-leader (hoặc leaderless). Nếu không, còn lựa chọn đơn giản hơn.
- Có cần khả dụng rất cao và chịu được đọc cũ hiếm không? → nếu có và không cần thứ tự chặt, leaderless (chỉnh R/W). Nếu không, single-leader là mặc định hợp lý nhất.
- Có thao tác cần đảm bảo tuyệt đối (check-and-set, khoá, số duy nhất) không? → nếu có, phần đó không giao cho quorum/eventual — tách ra dùng consensus (Module 6), dù phần còn lại dùng mô hình nào.
Nguyên tắc bao trùm: bắt đầu từ single-leader; chỉ đi sang multi-leader/leaderless khi có ràng buộc cụ thể buộc phải vậy. Phức tạp thêm phải được một yêu cầu thật biện minh.
4. Áp dụng — ba tình huống
- App thương mại điện tử một vùng, dữ liệu đơn hàng: ghi một nơi là ổn, cần nhất quán rõ (không bán trùng tồn kho). → Single-leader (đọc report từ follower, ghi qua leader). Phần "trừ tồn kho" cần đảm bảo → dùng cơ chế mạnh hơn cục bộ.
- Ứng dụng ghi chú đồng bộ nhiều thiết bị, dùng cả khi offline: phải ghi khi mất mạng rồi hoà. → Multi-leader (mỗi thiết bị một leader), gộp bằng CRDT/merge để không mất ghi.
- Kho đếm lượt xem/like toàn cầu, khả dụng trên hết, đọc cũ vài giây không sao: → Leaderless với W nhỏ (ghi nhanh), R vừa, gộp bằng bộ đếm CRDT — đây là chủ đích nới lỏng quorum dựa trên hội tụ CRDT, không cần giữ R+W>N như quy tắc quorum thông thường, vì bộ đếm CRDT tự hội tụ đúng bất kể thứ tự các bản tới.
Điểm chung của cách suy nghĩ: bắt đầu từ ràng buộc dữ liệu (ghi ở đâu, chịu cũ tới đâu, cần đảm bảo gì), không từ tên công nghệ.
5. Tự chọn — đến lượt bạn
Bạn đã có bảng so sánh và ba câu hỏi. Giờ tự chạy khung đó trên một hệ thật, không xem gợi ý trước. Đọc kỹ, tách hệ thành từng loại dữ liệu, chạy ba câu hỏi cho mỗi loại, rồi mới mở đáp án.
Một hệ vận hành cho chuỗi cửa hàng bán lẻ toàn quốc. (1) Audit log thao tác nhân viên: mỗi chi nhánh ghi log ngay tại quầy, kể cả lúc mất mạng (kho vùng sâu), đồng bộ về trung tâm khi có mạng lại. (2) Feature flag / cấu hình bật-tắt tính năng: mọi service ở mọi vùng đọc liên tục, hiếm khi ghi, chậm thấy thay đổi vài giây không sao — nhưng phải luôn đọc được. (3) Số phiếu giảm giá phát ra: mỗi mã chỉ được phát đúng một lần, tuyệt đối không được cấp trùng cho hai khách.
Q1Với ba loại dữ liệu của chuỗi cửa hàng trên, chạy ba câu hỏi quyết định và chọn cách tiếp cận cho mỗi loại (single-leader / multi-leader / leaderless / consensus). Vì sao KHÔNG nên ép cả ba dùng chung một mô hình?▸
(1) Audit log → multi-leader (mỗi chi nhánh như một leader). Câu hỏi 1: ghi phải ở nhiều nơi độc lập (nhiều chi nhánh, có lúc offline) → có → gần như buộc multi-leader. Log là append-only nên xung đột hiếm nghiêm trọng — gộp bằng cách nối các entry theo (thời điểm, chi-nhánh-id) thay vì cần chọn một bên thắng.
(2) Feature flag → leaderless. Câu hỏi 1: ghi không cần nhiều nơi độc lập (thay đổi cấu hình đến từ một bảng điều khiển trung tâm); câu hỏi 2: cần khả dụng rất cao toàn cầu và chịu được đọc cũ vài giây → có → leaderless, chỉnh R/W nghiêng hẳn về đọc-nhanh (đọc nhiều hơn ghi gấp nhiều lần).
(3) Số phiếu giảm giá → tách riêng, dùng consensus. Câu hỏi 3: có thao tác cần đảm bảo tuyệt đối (không cấp trùng — một dạng check-and-set) → có → phần này không giao cho quorum/eventual; nó cần linearizability/consensus (Module 6), dù dữ liệu khác của hệ dùng mô hình nào.
Vì sao không ép một mô hình: ba loại có ràng buộc trái ngược — audit log cần ghi-nhiều-nơi, feature flag cần khả-dụng-tối-đa, mã giảm giá cần đảm-bảo-tuyệt-đối. Một mô hình chung sẽ hoặc quá lỏng cho mã giảm giá (cấp trùng), hoặc quá chặt/chậm cho feature flag. Hệ trưởng thành trộn mô hình theo từng loại dữ liệu — đúng nguyên tắc bắt đầu từ ràng buộc, không từ tên công nghệ.
6. Pitfall — chọn theo hype hoặc một mô hình cho tất cả
Hai sai lầm ngược nhau nhưng cùng gốc (không xuất phát từ workload):
❌ "He noi tieng Y dung leaderless -> minh cung leaderless"
-> nhan phuc tap quorum/conflict cho du lieu von hop single-leader
-> va co the dung nham no cho thao tac can dam bao tuyet doi
❌ Ep MOT mo hinh cho MOI loai du lieu trong he
-> don hang (can chat) va dem like (chiu long) bi doi xu giong nhau
-> hoac qua chat (cham) hoac qua long (sai cho don hang)
Hệ quả: hoặc gánh phức tạp vô ích, hoặc dùng sai mức đảm bảo cho dữ liệu quan trọng.
Hướng đúng: chọn theo ba câu hỏi trên cho từng loại dữ liệu, không theo tên hệ nổi tiếng. Một hệ trưởng thành thường trộn: single-leader cho dữ liệu giao dịch, leaderless cho đếm/feed, và consensus riêng cho khoá/bầu leader. Mặc định bắt đầu single-leader; nâng cấp khi có ràng buộc buộc phải.
7. Cơ chế — vì sao single-leader là mặc định công nghiệp?
Bảng và khung ở trên nói cái gì hợp khi nào. Phần này đào một tầng xuống: vì sao đa số cơ sở dữ liệu quan hệ (PostgreSQL, MySQL) và nhiều hệ lớn mặc định single-leader — và cái giá cơ chế của việc rời bỏ nó.
Gốc rễ nằm ở một điểm quyết thứ tự ghi. Khi mọi ghi đi qua đúng một leader, leader áp chúng vào log theo một trình tự tuần tự; mọi follower chỉ việc phát lại log đó theo đúng thứ tự. Ba hệ quả rơi ra từ đúng một tính chất này:
- Không có write conflict — vì không bao giờ có hai ghi được chấp nhận "song song" mà không biết nhau (điều kiện xung đột ở bài 03 không thể thoả). Cả một lớp bài toán — phát hiện và giải xung đột, vector clock, CRDT — biến mất khỏi hệ.
- Nhất quán dễ suy luận — trạng thái đúng luôn là "log của leader đã áp tới đâu". Đọc từ leader thấy mới nhất; đọc từ follower chỉ trễ về thời gian. Nhưng cẩn thận: điều này không tự động miễn nhiễm kiểu đảo tiền tố (consistent-prefix, bài 02) — đảo đó sinh ra khi hệ bị phân mảnh (mỗi phân mảnh replicate độc lập, không có thứ tự ghi toàn cục giữa các phân mảnh), chứ không phải do "nhiều nguồn ghi". Chỉ single-leader không phân mảnh (một log duy nhất, tổng thứ tự) mới thật sự miễn nhiễm; single-leader có phân mảnh vẫn có thể vỡ consistent-prefix y như multi-leader/leaderless.
- Phục hồi đơn giản — một follower chết rồi sống lại chỉ cần phát tiếp log từ điểm nó dừng; không phải hoà giải hai lịch sử ghi đã phân kỳ.
Đó là lý do single-leader "miễn phí" về mặt khái niệm: nó dồn toàn bộ độ khó của việc sắp thứ tự về một nơi. Cái giá — cũng là cơ chế — chỉ lộ ở failover: khi leader chết, phải bầu leader mới và có nguy cơ mất các ghi leader cũ chưa kịp replicate (bài 01). Multi-leader và leaderless gỡ bỏ điểm-quyết-duy-nhất để lấy độ trễ ghi thấp và khả dụng, nên phải mua lại khả năng sắp thứ tự vừa đánh mất: multi-leader mua bằng conflict resolution, leaderless mua bằng quorum cộng version/vector clock. Không kiến trúc nào tránh được bài toán thứ tự — chúng chỉ trả giá ở chỗ khác.
Nhìn qua lăng kính này, "chọn replication" thực chất là chọn trả cái giá của thứ tự ghi ở đâu: tập trung về một điểm (single-leader — rẻ khi chạy, đau lúc failover), hay phân tán rồi hoà giải (multi-leader/leaderless — linh hoạt và khả dụng, nhưng gánh conflict/quorum). Khung ba câu hỏi ở §3 chính là cách hỏi "workload của mình sẵn lòng trả giá ở đâu".
- Designing Data-Intensive Applications (Kleppmann) — Chương 5, tổng kết — Kleppmann trình bày ba mô hình như phổ đánh đổi, không như thứ bậc; nhấn "tránh xung đột tốt hơn giải quyết" và "chọn theo yêu cầu, không theo mốt".
- Ý polyglot persistence (dùng nhiều kho/mô hình cho các loại dữ liệu khác nhau trong một hệ) — chuẩn thực hành ở hệ lớn; replication model cũng nên trộn theo loại dữ liệu.
Ghi chú: không có "best replication" — chỉ có "hợp workload". Kỹ năng cần rèn là hỏi đúng câu về dữ liệu rồi để câu trả lời chọn mô hình.
8. Liên hệ các bài khác
- Bài 01 — Single-leader: mặc định hợp lý; hiểu điểm mạnh (không xung đột) và điểm căng (failover) để biết khi nào nó đủ.
- Bài 03 — Multi-leader: chọn khi ghi phải ở nhiều nơi độc lập — kèm gánh conflict resolution.
- Bài 04 — Leaderless: chọn khi cần khả dụng cao + chỉnh nhất quán bằng R/W; nhớ quorum ≠ đảm bảo tuyệt đối.
- Module 6 — Consistency & consensus: với thao tác cần đảm bảo tuyệt đối, không mô hình replication nào đủ — cần consensus.
9. Tóm tắt
- Không có mô hình replication "tốt nhất"; mỗi cái thắng ở một vùng workload.
- Single-leader: đơn giản, không xung đột, nhất quán dễ suy luận — mặc định; giá là nút thắt ghi + failover.
- Multi-leader: ghi nhiều nơi + hoạt động khi phân tách — chọn cho đa datacenter/offline/cộng tác; giá là conflict.
- Leaderless: khả dụng cao + chỉnh nhất quán bằng R/W — chọn khi chịu nhất quán yếu; giá là không thứ tự toàn cục.
- Chọn bằng ba câu hỏi: ghi một hay nhiều nơi (kể cả khi phân tách)? chịu đọc cũ tới đâu? có thao tác cần đảm bảo tuyệt đối?
- Bắt đầu single-leader; nâng cấp khi ràng buộc buộc phải; một hệ thật thường trộn nhiều mô hình theo loại dữ liệu.
- Anti-pattern: chọn theo hype, hoặc ép một mô hình cho mọi dữ liệu → thừa phức tạp hoặc sai mức đảm bảo.
10. Tự kiểm tra
Q1Vì sao single-leader thường là 'mặc định hợp lý', và bạn nên đi sang multi-leader/leaderless khi nào?▸
Vì single-leader đơn giản nhất và không có write conflict (một nơi quyết thứ tự), nên nhất quán dễ suy luận và ít chỗ sai — đủ cho phần lớn ứng dụng. Phức tạp thêm của hai mô hình kia phải được một yêu cầu thật biện minh.
Đi sang multi-leader khi ghi phải ở nhiều nơi độc lập (đa datacenter cần ghi cục bộ, client offline, cộng tác thời gian thực). Đi sang leaderless khi cần khả dụng rất cao và chịu được đọc cũ hiếm, muốn chỉnh nhất quán bằng R/W. Nếu không có ràng buộc đó, single-leader thắng vì rẻ và dễ đúng.
Q2Một hệ cần: (a) ghi đơn hàng chính xác, (b) đếm lượt xem toàn cầu chịu cũ vài giây, (c) cấp mã giảm giá duy nhất không trùng. Chọn cách tiếp cận cho mỗi loại và giải thích.▸
Đây là ví dụ vì sao một hệ nên trộn mô hình theo dữ liệu:
- (a) Đơn hàng: cần nhất quán rõ, ghi một vùng ổn → single-leader (ghi qua leader, đọc report từ follower).
- (b) Đếm lượt xem: khả dụng trên hết, cũ vài giây không sao, tích luỹ → leaderless W nhỏ + bộ đếm CRDT (gộp không mất).
- (c) Mã giảm giá duy nhất: cần đảm bảo tuyệt đối (không trùng) → không giao cho quorum/eventual; tách ra dùng consensus/linearizability (Module 6).
Bài học: chọn theo ràng buộc từng loại dữ liệu, không một mô hình cho tất cả.
Q3Vì sao 'hệ nổi tiếng X dùng leaderless nên ta cũng dùng leaderless' là lý do chọn sai? Điều gì nên thay thế nó?▸
Vì lựa chọn của hệ X phản ánh workload của X (thường là khả dụng cực cao, chịu nhất quán yếu), không phải của bạn. Sao chép nó có thể bắt bạn gánh phức tạp quorum/conflict cho dữ liệu vốn hợp single-leader, và tệ hơn, dùng nhầm nó cho thao tác cần đảm bảo tuyệt đối (mà leaderless không cung cấp).
Thay bằng: trả lời ba câu hỏi về dữ liệu của chính bạn (ghi một hay nhiều nơi, kể cả khi phân tách? chịu đọc cũ tới đâu? có thao tác cần đảm bảo tuyệt đối?). Câu trả lời — không phải tên công nghệ — chọn mô hình. Bắt đầu từ single-leader và chỉ nâng cấp khi ràng buộc buộc phải.
Q4Câu hỏi 'có thao tác cần đảm bảo tuyệt đối không' đứng riêng trong khung quyết định. Vì sao nó không được quyết bởi lựa chọn replication model?▸
Vì cả ba mô hình replication đều không tự cung cấp đảm bảo tuyệt đối cho thao tác kiểu check-and-set/khoá/số-duy-nhất: single-leader vẫn có thể mất ghi lúc failover; multi-leader và leaderless không có thứ tự toàn cục (ghi song song). Quorum chỉ cho nhất quán xác suất.
Loại đảm bảo đó cần consensus/linearizability (Module 6) — một cơ chế đảm bảo mọi node đồng ý một thứ tự duy nhất. Nên trong khung quyết định, nó là câu hỏi tách riêng: dù phần lớn dữ liệu dùng mô hình replication nào, phần cần đảm bảo tuyệt đối được giao cho consensus. Đó là lý do các hệ thật chạy etcd/ZooKeeper bên cạnh kho dữ liệu chính.
Q5Một dịch vụ chỉ chạy trong một vùng, đọc gấp nhiều lần ghi, và cần dữ liệu nhất quán rõ ràng. Có nên nhảy sang leaderless 'cho hiện đại' không? Chọn gì và vì sao?▸
Không nên. Trả lời ba câu hỏi: ghi một nơi là đủ (một vùng), không cần ghi khi phân tách, cần nhất quán rõ ràng (không chịu đọc cũ tuỳ tiện). Không có ràng buộc nào buộc phải multi-leader hay leaderless.
→ Chọn single-leader: ghi qua leader (nhất quán, không xung đột), và vì đọc nhiều gấp bội, thêm nhiều follower để chia tải đọc — đúng điểm mạnh của single-leader. Nhảy sang leaderless chỉ để "hiện đại" sẽ nhận về quorum, read repair, conflict và nhất quán yếu hơn — phức tạp không có yêu cầu nào biện minh. Nguyên tắc: bắt đầu single-leader, chỉ nâng cấp khi ràng buộc buộc phải.
Bài tiếp theo: Module 2 — Tổng kết & cheat sheet
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
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