CRDT (kiểu dữ liệu nhân bản không xung đột)
1. Tổng quan
A. Định nghĩa
CRDT (Conflict-free Replicated Data Type, kiểu dữ liệu nhân bản không xung đột) là cấu trúc dữ liệu nhân bản được thiết kế sao cho dù nhiều bản sao (Replica) tự thực hiện cập nhật độc lập và trao đổi thay đổi của nhau theo thứ tự bất kỳ, chỉ cần các cập nhật được lan truyền đến mọi bản sao thì về mặt toán học chắc chắn hội tụ về cùng một trạng thái cuối cùng mà không cần bộ điều phối trung tâm hay quá trình đồng thuận (Strong Eventual Consistency, SEC).
CRDT là khái niệm do Marc Shapiro, Nuno Preguiça và cộng sự hệ thống hóa năm 2011, là lời giải dựa trên đại số (algebra) cho bài toán khó lâu đời trong hệ phân tán: "làm sao bảo đảm tính nhất quán mà các nút không phải đồng thuận mỗi lần". Ngày nay nó đã trở thành bộ máy cốt lõi của các kho dữ liệu phân tán như Redis (Active-Active CRDB), Riak, Azure Cosmos DB, các trình soạn thảo cộng tác thời gian thực như Figma, Google Docs, Apple Notes, và các thư viện ưu tiên cục bộ (Local-first) như Automerge, Yjs.
B. Bối cảnh ra đời và sự cần thiết
Trong môi trường nhân bản phân tán, khi nhiều nút đồng thời sửa cùng một dữ liệu thì tất yếu phát sinh xung đột (conflict). Lời giải truyền thống có hai hướng. Một là đồng thuận mạnh (consensus) như Paxos, Raft, yêu cầu sự đồng ý của đa số nút cho mỗi lần ghi; cách này chắc chắn về tính nhất quán nhưng bắt buộc có vòng khứ hồi mạng nên độ trễ lớn, và khi phân vùng mạng (partition) phải hy sinh tính sẵn sàng. Hai là cách dùng dấu thời gian để loại bỏ một bên như "lần ghi cuối thắng (LWW, Last-Write-Wins)"; hiện thực đơn giản nhưng có vấn đề cập nhật ghi trước bị mất một cách âm thầm.
Như định lý CAP chỉ ra, chừng nào còn tồn tại phân vùng mạng thì không thể đồng thời đạt hoàn hảo cả tính nhất quán (C) và tính sẵn sàng (A). CRDT là cách tiếp cận trong thế lưỡng nan này chọn tính sẵn sàng và khả năng chịu phân vùng (AP), nhưng khôi phục phần lớn tính nhất quán dưới dạng nhất quán cuối cùng mạnh (SEC). Ý tưởng cốt lõi là thiết kế phép hợp nhất (merge) về mặt đại số để thỏa mãn tính giao hoán, tính kết hợp và tính lũy đẳng. Khi ba tính chất này thỏa mãn, kết quả được xác định duy nhất bất kể thứ tự đến, trùng lặp hay trễ của cập nhật, nên các nút không cần chờ hay điều phối lẫn nhau mà vẫn có thể tự do chỉnh sửa ngoại tuyến rồi tự động hợp nhất sau. Lý do dữ liệu không bị hỏng khi hai người dùng cùng sửa một câu đồng thời trong trình soạn thảo cộng tác chính là nhờ bảo đảm hội tụ này.
C. Đặc điểm cốt lõi
Đặc điểm của CRDT được cô đọng thành bốn điểm. Thứ nhất, cập nhật không cần điều phối (coordination-free update) — tại thời điểm ghi không cần giao tiếp với nút khác nên độ trễ thấp và vẫn hoạt động khi ngoại tuyến. Thứ hai, hội tụ tất định — các bản sao nhận cùng tập cập nhật chắc chắn đạt cùng trạng thái bất kể thứ tự hợp nhất. Thứ ba, chịu phân vùng — dù mạng bị ngắt, mỗi mảnh vẫn phục vụ độc lập và tự động hợp nhất khi khôi phục. Thứ tư, tự động giải quyết xung đột — không xem xung đột là lỗi mà để quy tắc hợp nhất của cấu trúc dữ liệu hấp thụ một cách tất định. Các đặc điểm này có được bằng cái giá từ bỏ việc cưỡng chế bất biến mạnh và nhất quán toàn cục tức thời, nên khi áp dụng phải nhận thức rõ được gì và mất gì.
2. Nền tảng toán học của hội tụ — Nửa dàn (Semilattice)
Căn cứ để CRDT bảo đảm "không xung đột" nằm ở chỗ không gian trạng thái tạo thành nửa dàn hợp (Join Semilattice) và phép hợp nhất tính cận trên nhỏ nhất (Least Upper Bound, LUB) trên đó. Trong nửa dàn, phép hợp nhất ⊔ thỏa mãn ba tính chất sau.
flowchart TB
subgraph Props["3 tính chất mà phép hợp nhất (merge) phải thỏa mãn"]
C["Tính giao hoán (Commutativity)<br/>a ⊔ b = b ⊔ a<br/>→ không phụ thuộc thứ tự đến"]
A["Tính kết hợp (Associativity)<br/>(a ⊔ b) ⊔ c = a ⊔ (b ⊔ c)<br/>→ không phụ thuộc cách nhóm"]
I["Tính lũy đẳng (Idempotency)<br/>a ⊔ a = a<br/>→ nhận trùng lặp vô hại"]
end
C --> R["Hội tụ tất định (Strong Eventual Consistency)"]
A --> R
I --> R
R --> G["Các bản sao nhận cùng tập cập nhật<br/>chắc chắn có cùng trạng thái"]
Tính giao hoán bảo đảm kết quả như nhau dù thông điệp đến theo thứ tự nào, tính kết hợp bảo đảm kết quả như nhau dù nhóm lại hợp nhất theo cách nào, tính lũy đẳng bảo đảm kết quả không đổi dù nhận cùng một thông điệp nhiều lần (gửi lại, trùng lặp). Khi cả ba cùng thỏa mãn, trạng thái tăng đơn điệu (monotonic) trên dàn, và các bản sao tiến hóa theo những con đường khác nhau, nếu nhận cùng tập cập nhật, chắc chắn gặp nhau tại cùng một cận trên nhỏ nhất trên dàn. Đây là chứng minh cốt lõi cho khẳng định "hội tụ mà không cần đồng thuận" của CRDT.
Hàm ý thực tiễn của tính chất đại số này rất lớn. Dù mạng sắp xếp lại, nhân đôi hay làm trễ thông điệp, thậm chí nút ngoại tuyến vài ngày rồi quay lại, chỉ cần đẩy các cập nhật tồn đọng vào không cần theo thứ tự thì tính nhất quán được khôi phục. Tức là CRDT hạ cấp mạng không ổn định từ tiền đề của tính đúng đắn xuống thành biến số hiệu năng.
Tuy nhiên cần lưu ý rằng bảo đảm này có điều kiện "miễn là được chuyển đến". CRDT giả định lan truyền cuối cùng (eventual delivery) — cập nhật rốt cuộc sẽ đến mọi bản sao — nên không cứu được bản sao bị cô lập vĩnh viễn hay cập nhật bị mất mà không được gửi lại. Do đó trong thực tiễn luôn phải thiết kế kèm với CRDT một tầng lan truyền bảo đảm "chắc chắn sẽ được chuyển đến lúc nào đó" bằng đồng bộ chống entropy (anti-entropy) hoặc trao đổi trạng thái định kỳ.
3. Hai phương thức hiện thực — Dựa trên trạng thái (CvRDT) và dựa trên thao tác (CmRDT)
CRDT chia thành hai dòng tùy theo "trao đổi cái gì" giữa các bản sao. Một là dựa trên trạng thái (State-based, CvRDT) trao đổi toàn bộ trạng thái (hoặc delta), hai là dựa trên thao tác (Operation-based, CmRDT) phát quảng bá từng thao tác riêng lẻ. Về lý thuyết hai phương thức có thể chuyển đổi qua lại, nhưng có những đánh đổi thực tiễn rõ rệt về lượng truyền tải, giả định mạng và độ khó hiện thực.
flowchart LR
subgraph State["CvRDT dựa trên trạng thái"]
S1["Trạng thái bản sao 1"] -->|"Truyền trạng thái toàn bộ/delta"| M1["merge = LUB"]
S2["Trạng thái bản sao 2"] --> M1
M1 --> S3["Trạng thái hội tụ"]
end
subgraph Op["CmRDT dựa trên thao tác"]
O1["Bản sao 1"] -->|"Quảng bá thao tác"| CB["Chuyển giao tin cậy theo thứ tự nhân quả<br/>(exactly-once, causal)"]
CB --> O2["Áp dụng tại bản sao 2"]
end
Dựa trên trạng thái là bản sao định kỳ gửi toàn bộ trạng thái của mình cho láng giềng, và phía nhận lấy cận trên nhỏ nhất của hai trạng thái bằng hàm hợp nhất. Vì hợp nhất có tính lũy đẳng, giao hoán, kết hợp nên bền vững trước mất mát, trùng lặp, sắp xếp lại thông điệp, và an toàn cả trên cơ chế lan truyền lỏng lẻo như giao thức gossip. Nhược điểm là gửi toàn bộ trạng thái thì lượng truyền lớn; phương án giảm nhẹ là CRDT trạng thái delta (Delta-state CRDT) chỉ gửi phần thay đổi, được Redis Active-Active và các hệ thống khác áp dụng.
Dựa trên thao tác chỉ lan truyền các thao tác riêng lẻ như "thêm phần tử", "bộ đếm +1" nên hiệu quả băng thông tốt. Đổi lại, để bảo đảm tính đúng đắn, nó đặt ra tiền đề mạnh là tầng chuyển giao phải bảo đảm chuyển giao đúng một lần (exactly-once) và theo thứ tự nhân quả (causal order). Bởi nếu thao tác bị áp dụng trùng lặp (VD: tăng bộ đếm hai lần) thì kết quả bị hỏng. Các trình soạn thảo cộng tác thời gian thực ưa dùng dòng này, nhưng kèm theo cơ chế log và vector phiên bản để phát lại theo thứ tự các thao tác bị lỡ khi kết nối lại.
Tiêu chí thực tiễn phân định hai phương thức là cân bằng giữa giả định mạng và lượng truyền tải. Ở hạ tầng lỏng lẻo nơi gossip, gửi lại là chuyện thường ngày (di động, biên, P2P), dựa trên trạng thái vốn vô hại trước mất mát, trùng lặp sẽ an toàn; còn ở môi trường backend nơi broker bảo đảm vững chắc thứ tự và chuyển giao, dựa trên thao tác với hiệu quả băng thông tốt sẽ có lợi. Chẳng hạn, nếu một bộ đếm được 5 nút cập nhật hàng chục nghìn lần mỗi giây mà mỗi lần đều truyền toàn bộ theo kiểu dựa trên trạng thái thì gánh nặng lớn, nhưng với CRDT trạng thái delta chỉ gửi "phần của mục đã thay đổi" thì có thể giảm lượng truyền xuống vài chục lần mà vẫn giữ được tính bền vững của dựa trên trạng thái. Redis Active-Active chọn phương thức trạng thái delta cũng vì điểm cân bằng này.
A. Theo dõi quan hệ nhân quả — Vai trò của vector phiên bản
Để CRDT phân biệt "cập nhật đồng thời (concurrent)" với "cập nhật đi trước theo quan hệ nhân quả (happens-before)" thì cần biết thứ tự thời gian, nhưng đồng hồ vật lý không đáng tin do sai lệch giữa các nút. Vì vậy phần lớn CRDT dùng vector phiên bản (Version Vector) tập hợp các bộ đếm logic theo từng nút, hoặc dot, làm căn cứ hợp nhất. Nếu vector phiên bản của hai cập nhật không bao hàm lẫn nhau thì phán định là "xảy ra đồng thời" và áp dụng quy tắc hợp nhất (add-wins, bảo toàn đa giá trị, v.v.); nếu một bên bao hàm bên kia thì chỉ giữ lại bản mới nhất.
Cơ chế này là nền móng của tính đúng đắn nhưng đồng thời cũng là nguồn gốc của sự gia tăng siêu dữ liệu. Số nút càng nhiều thì vector phiên bản càng dài, và khi kết hợp với thẻ, tombstone của OR-Set thì trạng thái phình to. Do đó trong thực tiễn, quản lý vòng đời của siêu dữ liệu nhân quả — như định kỳ dọn dẹp (compaction) các dot đã ổn định hoặc quản lý định danh nút bằng ID ngắn có thể tái sử dụng — trở thành yếu tố bắt buộc của thiết kế.
4. Các loại CRDT tiêu biểu và cách hoạt động
Ví dụ đơn giản nhất là G-Counter (Grow-only Counter). Mỗi nút giữ riêng phần bộ đếm của mình và tăng nó, giá trị tổng là tổng phần của mọi nút, còn hợp nhất lấy giá trị lớn nhất của từng mục. Phép lấy giá trị lớn nhất có tính giao hoán, kết hợp, lũy đẳng nên hội tụ được bảo đảm.
Cụ thể, giả sử các nút A, B, C tổng hợp số lượt thích. Mỗi nút giữ vector {A:_, B:_, C:_} và chỉ tăng mục của mình. Sau khi A tăng ba lần, B tăng hai lần rồi trao đổi trạng thái, A có {A:3,B:0,C:0}, B có {A:0,B:2,C:0}. Hợp nhất là giá trị lớn nhất theo từng mục nên khi gộp hai trạng thái, cả hai bên đều thành {A:3,B:2,C:0} và tổng khớp nhau là 5. Ở đây dù trạng thái của A đến B hai lần do sự cố mạng, nhờ tính lũy đẳng của phép lấy lớn nhất mà kết quả không đổi khỏi {A:3,...} — đây là chỗ tính chất nhận trùng lặp vô hại hiện ra bằng con số. Để hỗ trợ cả giảm thì dùng PN-Counter ghép hai G-Counter cho tăng và giảm (giá trị tổng = tổng tăng − tổng giảm). Các bộ đếm như vậy được dùng rộng rãi để tổng hợp chỉ số cần tổng chính xác nhưng chấp nhận bất nhất tạm thời như lượt xem, lượt thích, tồn kho.
Dòng tập hợp (Set) tinh tế hơn. G-Set chỉ cho phép thêm nên đơn giản, nhưng ngay khi hỗ trợ xóa thì nảy sinh vấn đề "khi thêm và xóa xảy ra đồng thời thì bên nào thắng". 2P-Set có ràng buộc đã xóa một lần thì không thể thêm lại, còn OR-Set (Observed-Remove Set) được dùng nhiều trong thực tiễn gắn thẻ duy nhất cho mỗi lần thêm và để phép xóa chỉ xóa "những thẻ đã quan sát được", qua đó hiện thực tự nhiên ngữ nghĩa ưu tiên thêm (add-wins).
Giải thích thêm ý đồ thiết kế của OR-Set, xóa không có nghĩa "loại bỏ một phần tử cụ thể" mà mang ý nghĩa chính xác là "vô hiệu hóa các thẻ thêm của phần tử này mà tôi đã quan sát được cho đến giờ". Vì vậy nếu trong lúc một nút đang lan truyền phép xóa mà nút khác thêm cùng phần tử với thẻ mới, thì thẻ mới đó không thuộc đối tượng bị xóa và phần tử sống sót. Ngữ nghĩa add-wins này ngăn việc mất dữ liệu trái trực giác trong soạn thảo cộng tác kiểu "mục tôi vừa thêm lại bị biến mất vì thao tác xóa của người khác". Ngược lại, cũng tồn tại biến thể (remove-wins) cho những miền cần ưu tiên xóa, nên điểm thiết kế là chọn quy tắc thắng thua phù hợp với ngữ nghĩa nghiệp vụ. Dưới đây là luồng hợp nhất thêm và xóa đồng thời trong OR-Set.
sequenceDiagram
participant A as Bản sao A
participant B as Bản sao B
A->>A: add("x") → {x:tag1}
B->>B: add("x") → {x:tag2}
A-->>B: lan truyền {x:tag1}
B-->>A: lan truyền {x:tag2}
Note over A,B: Kết quả hợp nhất {x:tag1, tag2}
B->>B: remove("x") → chỉ xóa phần đã quan sát tag1,tag2
A->>A: add("x") → {x:tag3} (thẻ mới)
A-->>B: lan truyền {x:tag3}
Note over A,B: Cuối cùng {x:tag3} — phần thêm mới sống sót (add-wins)
Với cộng tác văn bản thì dùng CRDT chuỗi (RGA, LSEQ, Logoot, YATA của Yjs, v.v.). Mỗi ký tự được gán một định danh vị trí (position identifier) có thứ tự trù mật, để dù hai người dùng cùng nhập tại một điểm, vị trí chèn vẫn được sắp xếp tất định. Dòng thanh ghi (register) gồm LWW-Register chỉ giữ lại một trong các lần ghi song song bằng dấu thời gian, và MV-Register (Multi-Value) bảo toàn tất cả giá trị xung đột để tầng trên giải quyết.
Các dạng cơ bản này kết hợp với nhau tạo thành cấu trúc phức tạp hơn. Tiêu biểu là OR-Map đặt giá trị của mỗi khóa là một CRDT khác (bộ đếm, tập hợp, thanh ghi, map lồng nhau) và hợp nhất đệ quy theo từng khóa. Nhờ đó có thể biểu diễn toàn bộ một tài liệu JSON thành một CRDT, nên trong ứng dụng cộng tác, dù nhiều người dùng cùng sửa trường bất kỳ của tài liệu, việc hợp nhất vẫn an toàn theo đơn vị trường. Mô hình "bản thân JSON là CRDT" mà Automerge hướng tới chính là kết quả của sự hợp thành đệ quy này, và nó có ý nghĩa lớn ở chỗ nâng toàn bộ trạng thái ứng dụng thành đối tượng nhân bản, vượt ra ngoài từng kiểu dữ liệu riêng lẻ.
| Loại | CRDT tiêu biểu | Quy tắc hợp nhất (tóm lược) | Công dụng chính |
|---|---|---|---|
| Bộ đếm | G-Counter / PN-Counter | Giá trị lớn nhất, tổng theo nút | Lượt xem, lượt thích, tồn kho |
| Tập hợp | G-Set / 2P-Set / OR-Set | Hợp tập hợp, xóa dựa trên thẻ | Thẻ, giỏ hàng, theo dõi |
| Thanh ghi | LWW-Register / MV-Register | Dấu thời gian lớn nhất / bảo toàn đa giá trị | Giá trị cấu hình, trường hồ sơ |
| Chuỗi | RGA / LSEQ / YATA | Sắp xếp theo định danh vị trí | Tài liệu cộng tác, soạn thảo mã |
| Map | OR-Map | Hợp nhất đệ quy CRDT con theo khóa | Tài liệu JSON, trạng thái có cấu trúc |
5. So sánh — CRDT vs đồng thuận (Raft/Paxos) vs OT
Để hiểu CRDT cần chỉ ra vì sao nó khác với các phương án thay thế. Đồng thuận mạnh (Raft/Paxos) yêu cầu sự đồng ý của đa số cho mỗi lần ghi, mang lại tính nhất quán mạnh nhất là khả năng tuyến tính hóa (linearizability), nhưng đổi lại mỗi lần ghi cần vòng khứ hồi mạng và khi phân vùng thì phe thiểu số ngừng ghi. Ngược lại, CRDT ghi ngay tại chỗ rồi hợp nhất sau nên không có độ trễ và có thể chỉnh sửa ngoại tuyến, nhưng trạng thái giữa các bản sao có thể tạm thời khác nhau (nhất quán cuối cùng) và không thể cưỡng chế bất biến toàn cục (global invariant) như "số dư tuyệt đối không được âm". Vì vậy nơi cần bất biến mạnh như chuyển khoản số dư ngân hàng thì hợp với đồng thuận, còn nơi ưu tiên tính sẵn sàng như cộng tác, tổng hợp thì hợp với CRDT.
Nó cũng đối lập với OT (Operational Transformation, phương thức ban đầu của Google Docs) — công nghệ cạnh tranh lâu đời của trình soạn thảo cộng tác. OT "biến đổi" thao tác dựa trên thao tác của bên kia để khớp thứ tự, nhưng số tổ hợp của hàm biến đổi nhiều nên hiện thực phức tạp và thường giả định có máy chủ trung tâm. CRDT nhúng thứ tự vào chính cấu trúc dữ liệu nên hội tụ được cả khi không có máy chủ (P2P), có lợi cho kiến trúc ưu tiên cục bộ, nhưng có điểm yếu là siêu dữ liệu tích tụ như thẻ xóa, tombstone nên tốn bộ nhớ hơn. Thực tế Figma dùng CRDT biến thể tự phát triển, còn Google Docs vẫn duy trì OT — lý do lựa chọn phân hóa nằm ở đây.
Tóm lại, khác biệt của ba công nghệ được tóm tắt bằng câu hỏi "trả chi phí điều phối khi nào". Đồng thuận trả trước tại thời điểm ghi chi phí điều phối (vòng khứ hồi mạng, chờ đa số) để mua tính nhất quán mạnh; OT để máy chủ trung tâm trả chi phí biến đổi lúc chạy; còn CRDT đóng đinh quy tắc hợp nhất về mặt đại số tại thời điểm thiết kế cấu trúc dữ liệu để loại bỏ điều phối lúc chạy. Đổi lại, CRDT phải mang theo suốt quá trình vận hành gánh nặng về siêu dữ liệu và lựa chọn ngữ nghĩa đã chấp nhận khi thiết kế. Không công nghệ nào ưu việt tuyệt đối; phải lựa chọn theo các trục mức độ yêu cầu nhất quán, ngân sách độ trễ, nhu cầu ngoại tuyến, năng lực hiện thực của đội ngũ.
6. Chuyên sâu — Ví dụ áp dụng thực tiễn và xu hướng mới
Trong thực tiễn, việc áp dụng CRDT đang lan rộng nhanh chóng. Active-Active (CRDB) của Redis Enterprise là cấu trúc trong đó nhiều trung tâm dữ liệu cách xa nhau về địa lý mỗi nơi nhận ghi cục bộ và phục vụ với độ trễ thấp, đồng thời hợp nhất CRDT ở chế độ nền để hội tụ; nó được dùng cho phiên làm việc toàn cầu, giỏ hàng, bảng xếp hạng. Riak từ sớm đã cung cấp CRDT bộ đếm, tập hợp, map như kiểu dữ liệu hạng nhất, và Azure Cosmos DB cung cấp LWW và hợp nhất tùy biến làm tùy chọn giải quyết xung đột cho ghi đa vùng. Về phía công cụ cộng tác, Figma xử lý chỉnh sửa đồng thời quy mô lớn, còn các công cụ kiểu Linear, Notion xử lý hợp nhất sau khi chỉnh sửa ngoại tuyến dựa trên CRDT.
Hệ sinh thái thư viện cũng đã trưởng thành. Yjs của cộng đồng JavaScript cung cấp CRDT tài liệu, mảng, map, văn bản với hiệu năng cao và đã trở thành chuẩn trên thực tế cho trình soạn thảo cộng tác web, còn Automerge xử lý toàn bộ tài liệu JSON như CRDT và hỗ trợ cả lịch sử thay đổi, hoàn tác. CRDT chuỗi thời kỳ đầu bị chỉ trích vì mỗi ký tự gắn siêu dữ liệu, gây chi phí lưu trữ gấp nhiều lần kích thước tài liệu, nhưng các hiện thực gần đây gộp các lần chèn liên tiếp thành một khối và áp dụng mã hóa nhị phân nên đã giảm đáng kể chi phí này. Xu hướng gần đây có hai hướng. Thứ nhất, nghiên cứu nén và thu gom rác nhằm giảm chi phí không gian do siêu dữ liệu tombstone, thẻ (VD: dọn thẻ của thao tác đã ổn định) đang sôi động. Thứ hai, kết hợp với phong trào phần mềm ưu tiên cục bộ (Local-first), CRDT đang nổi lên như công nghệ nền tảng của kiến trúc ứng dụng hoạt động hoàn toàn không cần mạng và tự động đồng bộ khi có kết nối.
Từ góc nhìn Kỹ sư chuyên nghiệp Quản lý Thông tin, các hướng ra đề dự kiến có khả năng cao gồm ① Trình bày định nghĩa CRDT và nguyên lý bảo đảm SEC (nửa dàn, 3 tính chất) ② So sánh khác biệt và tiêu chí áp dụng giữa dựa trên trạng thái và dựa trên thao tác ③ Giải thích vị trí của CRDT trong quan hệ với CAP và thuật toán đồng thuận ④ Nêu các lưu ý khi áp dụng CRDT trong kịch bản cộng tác thời gian thực/DB đa vùng. Bố cục bài làm triển khai theo thứ tự "định nghĩa → nguyên lý hội tụ → các loại → so sánh phương án thay thế → chiến lược áp dụng" sẽ bảo đảm cả chiều sâu lẫn cấu trúc.
7. Lưu ý và hàm ý
Chọn lọc miền áp dụng là ưu tiên hàng đầu. CRDT phù hợp với dữ liệu mà "tự động hợp nhất cập nhật đồng thời không làm tổn hại ý nghĩa" (tổng hợp, thẻ, vị trí trong tài liệu). Nó không phù hợp với miền cần bất biến toàn cục mạnh như số dư, giới hạn trên của tồn kho, nên thiết kế lai dùng xen kẽ CRDT (ưu tiên tính sẵn sàng) và đồng thuận (ưu tiên tính nhất quán) theo đặc tính dữ liệu là thực tế.
Quản lý siêu dữ liệu và tombstone là đánh đổi cốt lõi của vận hành. OR-Set, CRDT chuỗi tích lũy thông tin xóa và thứ tự dưới dạng thẻ nên khi vận hành lâu dài bộ nhớ, không gian lưu trữ phình to. Nhất thiết phải đưa chiến lược thu gom rác, nén trạng thái, snapshot sau khi phán định thời điểm ổn định vào giai đoạn thiết kế; nếu xem nhẹ điều này sẽ dẫn đến suy giảm hiệu năng.
Xung đột ngữ nghĩa (semantic conflict) vẫn là việc của tầng trên. CRDT bảo đảm hội tụ ở mức cấu trúc dữ liệu, nhưng không phán đoán được "khi hai người sửa cùng một trường khác nhau thì giá trị nào đúng về mặt nghiệp vụ". Cần bảo toàn giá trị xung đột bằng MV-Register và thiết kế đồng thời UX, chính sách để người dùng, quy tắc nghiệp vụ giải quyết cuối cùng.
Làm rõ giả định tầng chuyển giao và khả năng quan sát. CRDT dựa trên thao tác giả định chuyển giao exactly-once và theo thứ tự nhân quả, nên độ tin cậy của hạ tầng nhắn tin (broker, vector phiên bản) gắn trực tiếp với tính đúng đắn. Phải có hệ thống khả năng quan sát (chỉ số hội tụ, độ trễ nhân bản, tốc độ tăng thẻ) để giám sát độ trễ hợp nhất và việc hội tụ thì mới phát hiện sớm sự cố.
Chuẩn hóa và khả năng liên tác vẫn đang phát triển. Mã hóa và quy tắc hợp nhất khác nhau theo từng hiện thực CRDT nên khả năng tương thích giữa các thư viện bị hạn chế. Khi áp dụng kiến trúc ưu tiên cục bộ, việc đánh giá rủi ro phụ thuộc vào một thư viện cụ thể (lock-in) và chuẩn bị trước định dạng dữ liệu, lộ trình chuyển đổi là quan trọng về trung và dài hạn.
Cần xem xét song song góc độ bảo mật và kiểm chứng. Trong cấu trúc hợp nhất P2P, ngoại tuyến, nút độc hại có khả năng chèn cập nhật bị thao túng hoặc giả mạo thẻ, nên phải đặt chữ ký, kiểm soát truy cập, log kiểm toán cho cập nhật ở tầng trên. Ngoài ra, tính đúng đắn của quy tắc hợp nhất phụ thuộc vào tính chất đại số, nên khi thiết kế CRDT tùy biến, bắt buộc phải có quy trình kiểm chứng tính giao hoán, kết hợp, lũy đẳng bằng kiểm thử dựa trên thuộc tính (property-based testing) để xác nhận hội tụ thực sự được thỏa mãn.
Tài liệu tham khảo
- Shapiro, Preguiça, Baquero, Zawirski, "Conflict-free Replicated Data Types", INRIA RR-7687, 2011. https://inria.hal.science/inria-00609399
- Redis Enterprise, "Active-Active geo-distributed Redis (CRDBs)". https://redis.io/docs/latest/operate/rs/databases/active-active/
- Tài liệu chính thức của Yjs. https://docs.yjs.dev/
- Trang chính thức của Automerge. https://automerge.org/
- Kleppmann et al., "Local-first software". https://www.inkandswitch.com/local-first/
Tóm tắt một câu: CRDT là kiểu dữ liệu nhân bản thiết kế phép hợp nhất có tính giao hoán, kết hợp, lũy đẳng để bảo đảm mọi bản sao hội tụ về cùng một trạng thái (SEC) mà không cần đồng thuận trung tâm, và được dùng rộng rãi như phương án thay thế thuật toán đồng thuận trong các lĩnh vực coi trọng tính sẵn sàng và chỉnh sửa ngoại tuyến như soạn thảo cộng tác thời gian thực và kho dữ liệu đa vùng.