Đồng thuận phân tán: Thống nhất một lịch sử đã commit khi có lỗi
Nhận diện consensus như bài toán điều phối để chọn một lịch sử đã commit duy nhất dù có độ trễ và partial failure, thông qua quorum intersection, leader term, replicated log, commit boundary và hành vi rõ ràng khi mất quorum.
Bản đồ học tập phát triển phần mềm bởi Tran Trong Thuc · Về dự án Atlas · Cập nhật lần cuối: 22 thg 9, 2026
Đồng thuận phân tán: Thống nhất một lịch sử đã commit khi có lỗi
Trong một cụm phân tán gồm 5 node gánh vác sổ cái dữ liệu trọng yếu, 2 node bất ngờ sập nguồn hoàn toàn sau một sự cố điện lưới trung tâm dữ liệu. 3 node còn lại vẫn liên tục nhận các lệnh ghi dồn dập từ client. Làm thế nào để 3 node này luôn đạt được sự đồng thuận tuyệt đối về một sự thật duy nhất của dữ liệu—không bế tắc (deadlock), không chia rẽ bè phái, và không bao giờ đánh mất một giao dịch đã chốt? Đó chính là bài toán cốt lõi của đồng thuận phân tán (consensus): xác lập sự thống nhất về một chuỗi trạng thái có thứ tự qua mạng bất đồng bộ, nơi các thành viên có thể chậm trễ hoặc lăn ra chết bất kỳ lúc nào.
Đồng thuận bảo đảm các node độc lập thống nhất một giá trị hoặc một lịch sử có thứ tự dù message bị trễ và một số node gặp lỗi. Việc sao chép dữ liệu thô chỉ là điều kiện cần; hệ thống cần một bảo chứng toán học để khẳng định chân lý.
💡 Quy tắc bỏ túi: Sao chép giúp phân tán dữ liệu, nhưng đồng thuận mới là thứ xác lập chân lý. Khi cụm mất quorum đa số, hãy chủ động dừng ghi (fail closed) ngay lập tức—tuyệt đối không bao giờ phá vỡ ranh giới commit để phục vụ các lệnh ghi ở nhánh thiểu số bị cô lập.
Tóm tắt
- Đồng thuận là thống nhất lịch sử đã commit; sao chép không tự động là đồng thuận: Việc gửi các entry nhật ký sang follower chỉ là sao chép; giao thức đồng thuận (consensus) bắt buộc các node phải thống nhất xem lịch sử nào có thẩm quyền tối cao và thiết lập ranh giới commit không thể chối cãi.
- Giao thoa Quorum bảo đảm tính an toàn qua các nhiệm kỳ: Cụm $N$ node cần một quorum đa số ($\lfloor N/2 \rfloor + 1$) để bầu leader hoặc chốt lệnh ghi. Vì hai tập đa số bất kỳ luôn giao nhau ít nhất một node, nhiệm kỳ mới luôn kế thừa trọn vẹn toàn bộ các mục log đã được commit trước đó.
- Bầu leader phân định quyền lực theo nhiệm kỳ logic (term/epoch): Các giao thức như Raft dùng quy trình bầu cử leader và số nhiệm kỳ tăng đơn điệu để bảo đảm chỉ có một coordinator duy nhất được phép xếp thứ tự nhật ký sao chép tại một thời điểm.
- An toàn (Safety) luôn xếp trên tiến triển (Liveness) khi phân vùng mạng: Khi đứt mạng chia cắt cụm 5 node thành nhánh đa số (3 node) và nhánh thiểu số (2 node), nhánh đa số tiếp tục tiến triển còn nhánh thiểu số bắt buộc phải từ chối ghi để ngăn chặn phân kỳ lịch sử.
- Cạm bẫy chết người: Đánh đồng một mục log vừa ghi đĩa cục bộ với một trạng thái đã commit. Nếu leader vừa append một entry vào log của mình rồi crash trước khi kịp đạt quorum xác nhận, entry đó chưa hề được commit và chắc chắn sẽ bị leader nhiệm kỳ mới đè bẹp và xóa sạch.
Replication không tự động là consensus
Replication trả lời: làm sao nhiều node có được các bản sao của state?
Consensus trả lời: làm sao các node đó thống nhất giá trị, leader hoặc lịch sử có thứ tự nào là authoritative?
Một primary có thể sao chép dữ liệu bất đồng bộ sang follower mà không chạy consensus protocol cho từng commit. Một leaderless store có thể replicate nhiều version rồi reconcile sau. Ngược lại, replicated state machine thường kết hợp cả hai ý: consensus quyết định log entry nào được committed, sau đó replication mang những entry đó tới các member.
Vì vậy các suy luận tắt sau là không an toàn:
ba replica -> consensus đã xảy ra
quorum read/write -> đã có một lịch sử consensus linearizable duy nhất
có leader -> leader vẫn còn authorityConsensus nói về quy tắc agreement, không phải chỉ về số lượng bản sao hay một node mang tên “leader”.
Safety và liveness kéo theo hai mục tiêu khác nhau
Hai từ giúp phân loại điều consensus system cố giữ:
- Safety / an toàn: không xảy ra điều xấu. Hai participant đúng không commit hai quyết định không tương thích cho cùng một vị trí.
- Liveness / khả năng tiến triển: cuối cùng vẫn xảy ra điều tốt. Proposal mới cuối cùng được commit khi các giả định cần cho tiến triển được thỏa mãn.
Trong một partition cứng, protocol có thể chủ động hy sinh liveness ở phía thiểu số để giữ safety. Từ chối write có thể chính là kết quả đúng.
Đây cũng là thói quen suy luận từ các bài trước: timeout hoặc peer unreachable không chứng minh peer đã chết. Vì vậy consensus protocol cần voting rule và history rule vẫn an toàn khi failure detection không hoàn hảo.
Bầu leader thiết lập authority hiện tại
Consensus protocol dựa trên leader thường tổ chức thời gian theo các thế hệ logic. Trong Raft, một node có thể trở thành candidate, xin vote từ peer và chỉ trở thành leader sau khi thắng election quorum cần thiết.
Một node nhớ rằng nó đã từng là leader là chưa đủ. Authority của nó phụ thuộc vào term hiện tại và quorum rule của protocol.
Leader election chỉ là một phần của consensus. Câu hỏi safety khó hơn nằm ở chuyện lịch sử được xử lý thế nào trước, trong và sau khi leadership đổi.
Replicated log tách proposed khỏi committed
Raft là consensus algorithm để quản lý một replicated log. Leader sắp proposal thành log entry có thứ tự rồi gửi chúng cho follower. Entry xuất hiện trên một hoặc nhiều node chưa tự động có nghĩa nó đã committed.
Commit boundary là ranh giới quan trọng:
- client gửi proposal;
- leader append entry cục bộ;
- follower sao chép entry;
- protocol quan sát điều kiện quorum cần thiết;
- entry trở thành committed theo rule của protocol;
- replica apply các entry đã committed vào state machine theo thứ tự.
Một entry chưa commit / uncommitted có thể biến mất hoặc bị ghi đè sau leadership change. Client hoặc operator không được đánh đồng “tôi thấy entry trong log của một node” với “cluster đã commit entry đó”.
Tài liệu failure hiện tại của etcd minh họa đúng boundary này: sau leader failure, write đã gửi nhưng chưa commit có thể mất, trong khi write đã committed được consensus rule bảo toàn.
Quorum intersection khiến hai majority không thể tách rời hoàn toàn
Với majority quorum đơn giản, bất kỳ hai đa số hợp lệ nào cũng có ít nhất một member giao nhau.
Với năm member:
quorum A = {1, 2, 3}
quorum B = {3, 4, 5}
điểm giao nhau = {3}Phần chồng lấp đó giúp protocol mang thông tin safety từ quyết định trước sang quyết định sau. Proof consensus thực tế có nhiều điều kiện hơn quan sát này, nhưng quorum intersection là hình dạng cốt lõi cần nhận diện.
Group số lẻ rất phổ biến vì thêm một node để thành group số chẵn thường tăng cost mà không tăng simple-majority failure tolerance:
| Số member | Majority | Số member lỗi vĩnh viễn chịu được trước khi mất quorum |
|---|---|---|
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
| 6 | 4 | 2 |
| 7 | 4 | 3 |
Điều này không có nghĩa “luôn dùng năm node” hoặc “thêm member là miễn phí”. Group rộng hơn đưa thêm replication, disk và network work vào consensus path.
Network partition tạo phía đa số và phía thiểu số
Xét consensus group 5 node bị phân vùng mạng thành hai nhóm 3 và 2.
Phía thiểu số có thể vẫn sống, còn disk và vẫn pass process health check. Nó chỉ thiếu số vote cần để thiết lập một lịch sử committed mới một cách an toàn.
Nếu toàn cluster mất quorum, write cần consensus phải dừng. etcd ghi rõ điều này: mất đa số nghĩa cluster không thể nhận write mới cho đến khi quorum được khôi phục hoặc disaster recovery chủ đích tạo cluster mới từ một recovery point đáng tin cậy.
Đó là lý do “ép node bị cô lập tiếp tục phục vụ write” thường là availability shortcut nguy hiểm, không phải một chỉnh sửa vận hành vô hại.
Consensus có failure model
Raft và consensus kiểu Paxos cổ điển thường được giải thích dưới giả định lỗi crash / crash failure cùng network delay: node có thể dừng, restart hoặc unreachable, nhưng protocol tự nó không được thiết kế để an toàn trước participant tùy ý nói dối.
Một participant Byzantine có thể nói dối, equivocate hoặc gửi thông tin bịa khác nhau cho từng peer. Byzantine fault-tolerant protocol cần giả định và cơ chế khác.
Đừng nâng guarantee chỉ bằng từ vựng. Nói “chúng tôi dùng Raft” không đồng nghĩa Byzantine fault tolerance, miễn nhiễm software bug, business logic đúng, hay an toàn trước correlated operator mistake.
Consensus có chi phí độ trễ vật lý
Agreement là coordination, và coordination đi qua máy khác.
Tài liệu etcd hiện tại mô tả consensus commit latency bị giới hạn bởi network round-trip time (RTT) và durable disk I/O. Quorum trải rộng theo địa lý có thể tăng tách biệt failure domain, nhưng cũng đưa thêm network latency vào đường thiết lập agreement.
Điều đó tạo tension thực tế:
phân bố rộng hơn theo failure domain
-> có thể sống tốt hơn trước local failure
-> thường tăng consensus latency
-> cần hiểu quorum placement nghiêm ngặt hơnVì vậy consensus phù hợp nhất với state thực sự cần một đường quyết định authoritative: cluster membership, leader ownership, metadata, coordination record, strongly ordered state-machine command và control state tương tự.
Consensus không biến mọi business effect thành exactly-once
Consensus group có thể quyết định log entry 184 được committed đúng một lần trong lịch sử nội bộ của nó. Điều đó không tự động khiến email, payment charge, webhook hay database write bên ngoài xảy ra exactly-once.
Ngay khi committed command kích hoạt effect bên ngoài consensus state machine, Delivery Semantics, idempotency, transaction và reconciliation lại trở nên quan trọng.
Giữ các boundary này tách biệt:
- consensus quyết định lịch sử authoritative trong scope của nó;
- replication phân phối state đó;
- consistency mô tả observer được phép nhìn thấy gì;
- delivery semantics mô tả xử lý message lặp hoặc bỏ sót;
- business correctness phụ thuộc vào cách effect đi qua các boundary đó.
Kịch bản production: leader cũ bị cô lập vẫn nhận write cấu hình
Một control-plane service lưu routing configuration trong consensus group 5 member. Một network failure cô lập hai member, bao gồm leader cũ, khỏi ba member còn lại.
Phía ba member elect leader mới và tiếp tục commit thay đổi configuration. Leader cũ bị cô lập vẫn reachable từ một internal admin tool, và một “availability fallback” tự chế cho phép tool đó write trực tiếp vào local store của leader cũ mà không có quorum.
Hậu quả: các kỹ sư vận hành chứng kiến hai cấu hình định tuyến hoàn toàn xung đột nhau. Khi kết nối mạng thông suốt trở lại, các lệnh ghi cục bộ từ phía thiểu số vĩnh viễn không thể trở thành một phần của lịch sử đồng thuận đã chốt, dù các hệ thống downstream có thể đã lỡ thực thi các hành động dựa trên dữ liệu sai lệch đó.
Nguyên nhân cốt lõi: cơ chế fallback tự chế mặc định xem leader đã biết gần nhất là có thẩm quyền kể cả sau khi nó đã mất quorum. Đội ngũ kỹ thuật đánh đồng tính còn sống của tiến trình với thẩm quyền đồng thuận và tự ý vượt qua ranh giới commit.
Cách khắc phục chuẩn: bắt buộc mọi thao tác ghi được đồng thuận bảo vệ phải có thẩm quyền do quorum hiện tại xác lập, kiên quyết từ chối hoặc chặn ghi (fail closed) ở nhánh thiểu số, định danh việc mất quorum như một trạng thái vận hành rõ ràng, và chỉ kích hoạt các side effect bên ngoài dựa trên dữ liệu đã chốt (committed) thay vì quan sát cục bộ chưa commit. Nếu quorum mất vĩnh viễn, phải kích hoạt quy trình khắc phục thảm họa theo tài liệu chuẩn thay vì tự tạo ra một lịch sử dữ liệu thứ hai tại chỗ.
Tự kiểm tra
Một group kiểu Raft có 5 member bị partition thành phía 2 member chứa leader trước đó và phía 3 member. Leader cũ vẫn reachable từ client nhưng không reach được ba member kia. Nó có thể an toàn tiếp tục commit entry mới chỉ vì trước partition nó là leader không?
Xem giải thích chi tiết
Không. Vai trò leader trước đó không thay thế quorum requirement hiện tại. Phía thiểu số 2 member không thể tạo majority của năm, nên không được commit lịch sử mới. Phía 3 member có thể elect leader hiện tại và tiếp tục tiến triển. Giữ safety yêu cầu phía thiểu số dừng consensus write dù điều đó làm giảm availability cho client vẫn bị route tới nó.
Checklist review
- Scope agreement: Consensus group đang làm authoritative cho giá trị, log hay metadata history nào?
- Quorum: Cần bao nhiêu member cho election và commit, và các member đó nằm trong failure domain nào?
- Authority: Term, epoch, ballot hoặc generation tương đương vô hiệu leader cũ như thế nào?
- Commit boundary: Operator và client có phân biệt state đã replicate nhưng chưa commit với committed state không?
- Partition behavior: Phía thiểu số trả gì khi không thể tạo quorum?
- Failure model: Protocol chỉ thiết kế cho crash fault hay cho mô hình mạnh hơn như Byzantine fault?
- Latency: Network RTT và durable-storage latency nào nằm trên consensus path?
- Recovery: Quy trình majority-loss recovery có được tài liệu hóa và test mà không âm thầm tạo hai authoritative history không?
Quy tắc cho agent
- Không suy consensus từ bản sao: Tìm election rule và commit rule thật trước khi claim một lịch sử authoritative.
- Nêu rõ quorum: Chỉ ra participant nào và bao nhiêu vote thiết lập authority hoặc commitment.
- Tôn trọng state chưa commit: Không nâng local log entry thành business truth chỉ vì một node đã persist nó.
- Fail closed khi mất quorum: Không phát minh write bypass tạo independent minority history.
- Tách scope: Phân biệt consensus, replication, consistency, delivery semantics và guarantee của external side effect.
- Xác minh failure model: Không mô tả crash-fault protocol là Byzantine fault tolerant nếu protocol thực tế không cung cấp thuộc tính đó.
Nguồn tham khảo
Các nguồn chính được kiểm tra ngày 2026-09-17:
Sao chép phân tán: Giữ các bản sao đúng qua sự cố và chuyển đổi dự phòng
Suy luận về sao chép phân tán qua quyền ghi, thứ tự cập nhật, ranh giới xác nhận, độ trễ, bắt kịp, rào chắn khi chuyển đổi dự phòng, đối soát nhiều bên ghi, vị trí bản sao và ranh giới với đồng thuận.
Khóa phân tán: Điều phối công việc độc quyền bằng lease và fencing
Suy luận về khóa phân tán như giao thức quyền sở hữu dựa trên lease với identity, renewal, fencing, kiểm soát tranh chấp và failure behavior tường minh thay vì xem nó như mutex chạy qua network.