Chapter 9: Consistency và Consensus - Nhất quán và Đồng thuận: Consistency Guarantees và Linearizability
(Dựa theo sách Designing Data Intensive Application)
Ở phần về Những vấn đề trong hệ thống phân tán, chúng ta chốt lại được những ý sau:
- Network không đáng tin cậy: packet có thể bị lost, reorder, dupplicate và có độ trễ không thể dự đoán
- Đồng hồ không chính xác hoàn toàn
- Node có thể dừng hoặc crash tại bất cứ thời điểm nào
Consistency Guarantees
3 cấp độ consistency từ cao nhất tới thấp nhất:
- Strong consistency: Tất cả các node nhìn thấy cùng một giá trị tại cùng một thời điểm
- Eventual consistency: Nếu không có cập nhật mới, tất cả các bản sao của dữ liệu sẽ hội tụ về cùng một giá trị theo thời gian. (Most replicated db provide at least)
- Causal consistency: Một thao tác chỉ có thể được nhìn thấy sau khi tất cả các thao tác trước đó mà nó phụ thuộc vào đã được áp dụng
Linearizability (Strong Consistency) - Tuyến tính
Linearizability “behave as though there is only a single copy of the data, and all operations on it are atomic” - Đại ý là dữ liệu đọc luôn là dữ liệu up-to-date, đây là một recency guarantee.
Hình 9-1 dưới đây là 1 VD không tuân thủ Linearizability, dẫn đến sự "hỏi chấm" từ các fan bóng đá.
cas: Toán tử Compare And Set. cas(x,a,b) trong đó x là biến cần thay đổi, a là giá trị tại thời điểm ban đầu - compare value b, b là giá trị mới cần set.
Như hình 9-4, ta có thể thấy các client thao tác trên distributed database giống như đang thao tác trên chỉ 1 DB. Các hành động read sau khi write luôn trả về 1 kết quả duy nhất -> tính nhất quán mạnh.
Serializability và Linearizability thường bị nhầm lẫn với nhau Serializability là 1 isolation property của transactions where every transaction may read and write multiple objects (rows, documents, records). Serializability guarantees that transactions behave the same as if they had executed in some serial order (each transaction running to completion before the next transaction starts). Thuộc tính này cho phép có sự xáo trộn trong thứ tự chạy các transaction.
Linearizability is a recency guarantee on reads and writes of a register (an individual object). It doesn’t group operations together into transactions, so it does not prevent problems such as Write skew. Trừ khi thêm measure như là Materialzing Conflict
Áp dụng Linearizability
Locking và Leader Election
Trong single leader replication cần đảm bảo chỉ có 1 leader. Trong trường hợp leader down hay crash, có 1 cách để bầu leader là sử dụng lock. Tức là mỗi node khi khởi chạy để cố gắng đề giành lock, node nào giành được thì trở thành leader. Không cần biết lock này implement sao, nó bắt buộc phải tuyến tính, tức là tất cả các node phải thống nhất 1 leader, không thì sẽ xảy ra hiện tượng split brain.
Constraint và Uniqueness Guarantees
- Username hay email phải unique
- Back account không bị âm
- 2 người không cùng đặt trùng lịch Tất cả những điều kể trên đều yêu cầu 1 giá trị mới nhất mà tất cả các node đều đồng ý
Cross channel dependencies
Hình ảnh trên hợp với trường hợp về service thumbnail.
Có 1 khả năng nhánh bên message queue sẽ nhanh hơn tốc độ replicate internal trong file storage, dẫn tới hai khả năng: bước 5 fetch lên không gì cả hoặc 1 phiên bản cũ của tấm hình cần resize. Lúc này vấn đề xảy ra: tấm hình fullsize lưu xuống và tấm hình resize sẽ bị không nhất quán trong Storage.
Nếu File Storage đạt linearizability thì vấn đề sẽ biến mất. Đó không phải là cách duy nhất để tránh race condition, nhưng là cách đơn giản nhất.
Triển khai Linearizability
Xem lại 3 mô hình replication có khả năng khiến chúng tuyến tính được không nhé:
- Single leader replication: thường tuyến tính, tuy nhiên 1 số loại DB không tuyến tính (VD do dùng snapshot isolation)
- Multi leader replication: không tuyến tính, chính vì các lệnh ghi được viết trên nhiều node leader và được replicate bất đồng bộ tới các node khác.
- Leaderless replication: có thể không tuyến tính, tuỳ thuộc vào cách config của quorum
Nhìn vào hình 9.6 ta có thể thấy kể cả dùng strict quorum vẫn có thể không giữ được tính linearizability do network delay. Để giữ tính tuyến tính, Reader cần thực hiện Read Repair 1 cách đồng bộ (với sự đánh đổi performance)
Cost of Linearizability
Multileader thường là một lựa chọn tốt cho hệ thống multi-datacenter replication.
Quan sát hình 9.7, ta có thể thấy chuyện network partition là chuyện không thể tránh khỏi (Có thể xem lại phần về Unreliable Network).
Trong trường hợp đó cần có 1 leader ở mỗi datacenter để mỗi datacenter có thể hoạt động bình thường. Lúc này thì dữ liệu writes từ 1 datacenter sẽ relicate bất đồng bộ sang datacenter khác, dữ liệu writes chỉ đơn giản là được thêm vào queue và chờ khi network quay lại để exchange.
Nếu áp dụng single-leader trong trường hợp này thì client ở phía follower datacenter sẽ không thể contact với leader để thực hiện ghi xuống DB, hay bất kỳ tác vụ đọc nào thực hiện trên các client này sẽ lấy lên dữ liệu có thể bị stale.
CAP Theorem
Định lý CAP: "either Consistent or Available when Partitioned". Trong 1 hệ thống dữ liệu phân tán, khi xảy ra network split, các dữ liệu giữa các phần mất kết nối không thể đảm bảo nhất quán với nhau (do chúng không thể giao tiếp, đương nhiên). Tuy nhiên như VD về các datacenter ở trên, chúng vẫn có thể phục vụ user 1 cách độc lập, duy trì tính Availability. Đôi khi việc thiếu nhất quán giữa các phần của cơ sở dữ liệu khiến dữ liệu bị sai lệch, điều này quan trọng với các hệ thống yêu cầu độ chính xác cao. Đây là 1 trade-off =))
(To be continued - Chờ đón phần sau về chủ đề này tiếp nhé)
All rights reserved
Bình luận