System Design — Bài 11: Nhất quán trong hệ phân tán: CAP, Raft và đồng hồ logic
Client timeout khi chuyển tiền có thể xảy ra trước xử lý, trong xử lý hoặc sau commit. Hệ phân tán buộc chúng ta thiết kế cho trạng thái chưa biết đó. CAP, consensus và đồng hồ logic giúp gọi tên các bảo đảm, nhưng mỗi cơ chế chỉ giải một phần bài toán.
Khóa học System Design: mục lục 21 bài — bạn đang đọc bài 11.
Vì sao hệ phân tán khó
Mạng có thể chậm, mất gói hoặc chia thành những nhóm không liên lạc được. Node cũng có thể tạm dừng lâu do tài nguyên hoặc runtime. Từ bên ngoài, ta khó phân biệt một máy chết với một máy đang rất chậm.
Ví dụ service đặt hàng timeout khi gọi thanh toán. Nếu tự kết luận chưa thu tiền rồi gửi một yêu cầu mới, khách có thể bị trừ hai lần. Cần dùng định danh nghiệp vụ ổn định và cơ chế tra trạng thái, thay vì dựa vào việc có nhận response hay không.
Thiết kế cần mô tả timeout, retry, idempotency và recovery như một phần của đường đi bình thường. Lỗi từng phần mới là điểm đặc biệt: một số thành phần vẫn hoạt động, nên hệ có thể tiếp tục tạo tác động trong lúc phần khác mất liên lạc.
CAP đọc cho đúng

Xem sơ đồ đầy đủ: CAP đọc cho đúng
CAP không phải thực đơn chọn hai chữ bất kỳ. Khi partition khiến các nhóm node không phối hợp được, hệ không thể đồng thời bảo đảm linearizability và phục vụ thành công mọi request tới node không lỗi theo nghĩa của định lý.
Linearizability có thể hiểu là thao tác trông như diễn ra trên một bản dữ liệu duy nhất và tôn trọng thứ tự thời gian thực. Nhánh cần giữ bảo đảm này có thể phải từ chối hoặc chờ khi không đủ điều kiện phối hợp. Nhánh tiếp tục phục vụ ở nhiều phía phải chấp nhận mức nhất quán yếu hơn và có thể cần giải xung đột.
Chữ C của ACID nói về việc giữ các bất biến dữ liệu qua giao dịch, không phải cùng định nghĩa với C trong CAP. Cũng không nên gắn nhãn toàn bộ ứng dụng: một ví có thể nghiêm ngặt ở chuyển tiền nhưng cho lịch sử hiển thị từ replica chậm hơn.
Strong vs Eventual consistency

Xem sơ đồ đầy đủ: Strong vs Eventual consistency
“Strong consistency” là cách nói rộng, nên khi thiết kế phải chỉ rõ bảo đảm cần có. Ví dụ sau khi một lần ghi hoàn tất, một lần đọc bắt đầu sau đó có phải thấy giá trị đó hoặc giá trị mới hơn hay không? Eventual consistency hướng tới hội tụ khi không còn cập nhật mới và cơ chế truyền, giải xung đột hoạt động theo giả định.
Đọc replica chậm có thể làm người dùng vừa sửa hồ sơ lại thấy bản cũ. Có thể định tuyến lần đọc liên quan về primary hoặc dùng cơ chế bảo đảm read-your-writes. Không phải mọi luồng đều cần trả cùng mức chi phí đồng bộ.
Two-Phase Commit (2PC) giải quyết quyết định commit hoặc abort giữa các bên tham gia. Nó không tự định nghĩa isolation hay cách mọi lượt đọc quan sát dữ liệu. Phải phân biệt atomic commit với consistency của các thao tác đọc và ghi.
Consensus & Raft

Xem sơ đồ đầy đủ: Consensus & Raft
Consensus giúp các node thống nhất các quyết định dù có lỗi. Raft tổ chức quanh leader election và log replication. Với năm node, đa số là ba. Khi mất khả năng liên lạc với đa số, một phía không được tùy ý tiếp tục xác nhận log mới.
Hãy phân biệt node tự nghĩ mình là leader với quyền commit hợp lệ. Sau partition, leader cũ có thể chưa biết vai trò đã thay đổi; term và các quy tắc log, quorum bảo vệ tính an toàn. Node mới không chỉ được chọn vì nhanh nhất, mà phải thỏa điều kiện giao thức.
Cụm số lẻ thường có lợi về số node so với mức chịu lỗi. Số lượng node lớn hơn cũng tăng chi phí phối hợp, nên không thể thêm vô hạn để mọi thứ tốt hơn.
Thời gian trong hệ phân tán

Xem sơ đồ đầy đủ: Thời gian trong hệ phân tán
Hai máy có thể lệch đồng hồ, và đồng hồ có thể được điều chỉnh. Vì vậy timestamp của máy nhận nhỏ hơn máy gửi không chứng minh message đi ngược thời gian. Dùng giờ vật lý đơn thuần để sắp thứ tự nghiệp vụ có thể sai.
Lamport clock tăng bộ đếm theo sự kiện và khi nhận message lấy giá trị lớn hơn rồi tăng. Nếu sự kiện A gây ra B, đồng hồ logic của A nhỏ hơn B. Chiều ngược lại không luôn đúng: số nhỏ hơn chưa đủ chứng minh quan hệ nhân quả. Vector clock cung cấp thêm thông tin để phát hiện một số sự kiện không có quan hệ trước sau.
Với chat, nếu yêu cầu thứ tự trong một conversation, cần một cơ chế cấp sequence hoặc phân vùng xử lý phù hợp. Một ID có timestamp không tự bảo đảm thứ tự nghiệp vụ khi nhiều máy đồng thời sinh tin.
Cụm năm node khi mạng chia thành hai nhóm
Nhóm A: node 1, 2, 3 | Nhóm B: node 4, 5
3/5 | 2/5
Quorum đa số = 3
Nhóm A có thể tiến triển nếu bầu leader và log hợp lệ.
Nhóm B không được tự xác nhận log mới cần đa số.
Timeout != bằng chứng thao tác chưa diễn ra.
Timestamp nhỏ hơn != bằng chứng sự kiện xảy ra trước.Quorum đếm node chưa đủ để triển khai Raft: còn term, điều kiện bầu leader và quy tắc commit log. Read path cần cơ chế thích hợp nếu muốn linearizability. Một node tự nhận mình là leader chưa chứng minh có quyền xác nhận thao tác.
Thuật ngữ cần nhớ
CAP — Consistency, Availability, Partition Tolerance: Nhất quán theo thứ tự thời gian thực; mọi request tới node không lỗi được phản hồi; và khả năng xét hoạt động khi mạng bị chia cắt. Khi partition xảy ra, không thể bảo đảm đầy đủ cả hai thuộc tính đầu theo định nghĩa của định lý.
ACID — Atomicity, Consistency, Isolation, Durability: Bốn thuộc tính giao dịch: nguyên tử (tất cả hoặc không); nhất quán (giữ bất biến dữ liệu); cô lập (kiểm soát ảnh hưởng đồng thời); bền vững (dữ liệu đã commit tồn tại theo cam kết). Chữ C ở đây khác consistency trong định lý CAP.
2PC — Two-Phase Commit: Giao thức cam kết hai pha: chuẩn bị rồi quyết định commit/abort chung giữa các bên tham gia; có thể bị chặn khi lỗi điều phối, không tự định nghĩa mức isolation.
Bài tập tự thực hành
Cụm năm node bị chia thành ba và hai.
Gợi ý kiểm tra lời giải
Giải thích đa số và khả năng tiến triển theo giao thức; không nói mọi node tự nhận leader đều có quyền commit.
Tự kiểm tra sau bài học
Giải thích C trong CAP khác C trong ACID.
Nêu bảo đảm đọc sau ghi cần có cho từng luồng.
Không dùng 2PC hoặc timestamp như đáp án cho mọi loại consistency.
Đọc thêm từ tài liệu gốc
Raft: In Search of an Understandable Consensus Algorithm
Tiếp tục lộ trình
Bài trước — Giao tiếp giữa service: HTTP, gRPC, queue và realtime
Bài tiếp — Saga, Outbox và resilience: giữ dữ liệu đúng khi service lỗi
Site Admin
Engineer and writer. Building things with TypeScript and distributed systems.
Bình luận (0)
Bạn cần đăng nhập bằng Google để bình luận.
Hãy là người bình luận đầu tiên.

