[System Design] Strong Consistency: Khi dữ liệu "chuẩn không cần chỉnh" là mệnh lệnh sống còn
Chào anh em, lại là mình đây.
Làm backend, chắc hẳn anh em đã từng nghe sếp vỗ vai giao task kiểu: "Em làm cái luồng chuyển tiền này cho cẩn thận nhé, sai một ly là công ty đi một sải đấy".
Trong những hệ thống liên quan đến tiền bạc, tài sản hay những thứ không thể có sự sai lệch (như book một cái ghế trống duy nhất trên chuyến bay), chúng ta không thể code kiểu "từ từ rồi nó sẽ đúng" được. Dữ liệu phải chính xác tuyệt đối ngay tại thời điểm người dùng bấm nút. Đó là lúc chúng ta phải lôi vũ khí hạng nặng mang tên Strong Consistency (Nhất quán mạnh) ra để giải quyết.
Hôm nay, mình sẽ bóc tách khái niệm này để anh em hiểu rõ bản chất và cái giá phải trả khi sử dụng nó
1. Strong Consistency rốt cuộc là cái gì?
Hiểu một cách ngắn gọn nhất theo định nghĩa của sách giáo khoa: Một khi dữ liệu đã được ghi (Write) thành công, bất kỳ thao tác đọc (Read) nào ngay sau đó, từ bất kỳ ai, ở bất kỳ đâu, cũng phải trả về giá trị mới nhất vừa được ghi.
Hãy lấy ví dụ thực tế cho dễ ngấm: Bạn mở app ngân hàng, tài khoản đang có 100 triệu. Bạn vừa bấm chuyển 20 triệu cho người yêu. Lệnh chuyển báo thành công.
- Ngay giây tiếp theo, bạn lấy một cái điện thoại khác, đăng nhập vào để check số dư.
- Hệ thống bắt buộc phải báo số dư là 80 triệu.
- Nếu nó báo 100 triệu (dù chỉ lag trong nửa giây), bạn sẽ hoảng loạn gọi lên tổng đài mắng vốn.
Sự bảo đảm chắc nịch rằng "Đã ghi xong là tất cả cùng thấy bản cập nhật mới nhất" chính là Strong Consistency.
2. Sự thật phũ phàng dưới tầng Database
Để đạt được sự nhất quán tuyệt đối này trong môi trường phân tán (Distributed System - nơi database có 1 con Master và nhiều con Slave), hệ thống phải đánh đổi bằng mồ hôi và nước mắt.
Cơ chế hoạt động ngầm (Synchronous Replication):
- User bấm nút gửi dữ liệu cập nhật lên Database Master.
- DB Master ghi dữ liệu vào ổ cứng của nó.
- Thay vì trả lời "Thành công" luôn cho User, DB Master sẽ "khoá" (lock) yêu cầu đó lại. Nó bắt đầu gửi bản copy dữ liệu sang tất cả các DB Slaves.
- Nó phải ngồi đợi tất cả (hoặc phần lớn) các DB Slaves xác nhận (ACK) rằng: "Em cũng ghi xong rồi đại ca ơi".
- Lúc này, DB Master mới nhả lock và báo về cho User: "Ghi thành công hoàn toàn rồi nhé".
3. Cái giá đắt đỏ của sự "Hoàn hảo"
Trên đời này không có bữa trưa nào miễn phí. Việc bắt mọi thứ phải chờ đợi nhau để đảm bảo dữ liệu đồng nhất sinh ra hai "nỗi đau" cực lớn cho hệ thống:
- Tốc độ rùa bò (High Latency): Thời gian để hoàn thành một thao tác Ghi (Write) bằng tổng thời gian nó ghi trên Master cộng với thời gian mạng truyền đi và ghi trên các con Slaves. Nếu một con Slave nằm ở tít bên Mỹ mạng lag, toàn bộ hệ thống phải chờ nó. Trải nghiệm người dùng sẽ bị chậm đi đáng kể.
- Tính sẵn sàng kém (Low Availability): Đây là nỗi đau của định lý CAP (CAP Theorem). Giả sử đứt cáp quang biển, con DB Master không thể liên lạc được với DB Slave. Để bảo vệ tính "Nhất quán mạnh", hệ thống thà từ chối luôn yêu cầu Ghi của user (báo lỗi hệ thống) chứ tuyệt đối không chấp nhận việc Master và Slave chứa dữ liệu khác nhau. Hệ thống sẽ có nguy cơ bị sập (downtime) cao hơn khi có sự cố mạng.
4. Khi nào thì nên xài Strong Consistency?
Vì nó "chậm và khó tính", anh em tuyệt đối không vác Strong Consistency đi áp dụng bừa bãi cho mọi chức năng. Chỉ dùng nó cho những core domain (nghiệp vụ cốt lõi) không thể sai số:
- Core Banking / Ví điện tử: Trừ tiền, cộng tiền, tính lãi suất. Không ai chấp nhận việc chuyển tiền xong mà hệ thống báo "đợi tí để đồng bộ".
- Hệ thống đặt chỗ (Booking/Ticketing): Vé máy bay, vé xem phim. Một cái ghế ở rạp CGV không thể bán cho 2 người cùng một lúc chỉ vì server chưa kịp đồng bộ dữ liệu.
- Quản lý kho hàng (Inventory) khắt khe: Nhập/xuất kho sản phẩm vật lý đắt tiền mà số lượng có hạn (như bán siêu xe, bán nhà).
Chốt hạ
Strong Consistency giống như một ông kế toán già khó tính: Làm việc rất chậm, kiểm tra giấy tờ qua 3-4 cửa, bắt mọi người phải chờ đợi, nhưng một khi ổng đã đóng mộc xuất quỹ thì số liệu chuẩn xác 100%, không lệch một cắc.
Làm System Design là làm bài toán của sự đánh đổi (Trade-off). Nắm được ranh giới khi nào cần tốc độ nhanh, khi nào cần dữ liệu chính xác tuyệt đối sẽ giúp anh em thiết kế ra một kiến trúc vững chãi, không bị "over-engineering" (làm lố) mà cũng không lo đền tiền vì bug mất data.
Anh em từng làm dự án nào bắt buộc phải xài Strong Consistency chưa? Quá trình config database (như MySQL hay PostgreSQL) để đạt được cái này có hành anh em lên bờ xuống ruộng không? Để lại comment chém gió nhé!
All rights reserved