Tham gia bản thử Hanzo và được giảm 50% mọi gói trả phí

Khai tử Raft: từ đồng thuận ZooKeeper đến Lux Quasar, liên kết nguyên bản

Cách Hanzo Datastore thay động cơ NuRaft bên dưới ClickHouse Keeper bằng Lux Quasar — đồng thuận hậu lượng tử, không người dẫn đầu, liên kết thẳng vào máy chủ C++ — trong khi giữ nguyên ZooKeeper API mà bản sao đang nói.

Trong trang này

Hanzo Datastore ngày nay điều phối các bảng nhân bản theo cách ClickHouse làm: một Keeper nhúng, tương thích ZooKeeper, chạy Raft bên trong tiến trình máy chủ. Cách đó chạy được. Đó cũng là thành phần cổ điển cuối cùng, dựa trên người dẫn đầu, và tiền lượng tử trong chồng này. Bài này nói chúng tôi khai tử nó thế nào, và vì sao "khai tử ZK" không có nghĩa là viết lại phần nhân bản.

Tách Keeper: API đối diện động cơ

Phản xạ khi nghe "thay ZooKeeper" là tưởng tượng phải đụng tới mọi Replicated*MergeTree. Bạn không phải làm vậy, vì ClickHouse Keeper vốn đã là hai thứ tách được, bện vào một daemon:

  1. ZooKeeper API — một cây khóa-giá trị tuyến tính hóa được, với nút tuần tự, phiên bản, và watch. Trong mã nguồn đây là KeeperStorage, được KeeperStateMachine bọc lại (src/Coordination/KeeperStateMachine.h, class IKeeperStateMachine : public nuraft::state_machine). Đây là hợp đồng. Mọi bảng nhân bản, mọi truy vấn system.zookeeper, mọi bầu người dẫn đầu đều nói bằng nó.

  2. Động cơ đồng thuận — thứ nhận một dòng yêu cầu ghi, khiến một túc số nút thống nhất thứ tự của chúng, rồi gọi commit(log_idx, data) trên máy trạng thái theo đúng thứ tự đã thống nhất. Hôm nay đó là NuRaft: KeeperServer::launchRaftServer (src/Coordination/KeeperServer.cpp) dựng một nuraft::raft_server, một asio_service, một KeeperStateManager, và một KeeperLogStore.

Nhận xét gọn, nhận xét của Rich Hickey, là KeeperStateMachine đã được viết trên giao diện đồng thuận tổng quát (nuraft::state_machine: pre_commit, commit, rollback, ảnh chụp). Nó không biết và không quan tâm Raft nằm bên dưới. Động cơ là một giá trị có thể đổi, không phải chỗ hàn chết vào API.

Vậy: giữ máy trạng thái, thay động cơ. ZooKeeper API mà nhân bản phụ thuộc vẫn nguyên. NuRaft, việc bầu người dẫn đầu, và đòi hỏi chạy một túc số Raft riêng là những gì chết.

Cái gì thay nó

Động cơ trở thành Quasar — đồng thuận không người dẫn đầu, dựa trên DAG, hậu lượng tử, từ Lux. Việc của Quasar ở đây trùng việc của Raft: thống nhất thứ tự của một nhật ký và ra hiệu khi một mục đã chốt. Khác ở cách thống nhất — không có một người dẫn đầu để chuyển khi hỏng, chữ ký ML-DSA thay cho chữ ký cổ điển, và tính chốt theo ngưỡng tin cậy thay cho đa số của một nhiệm kỳ cố định.

Điểm quyết định: Quasar không phải dịch vụ Go mà chúng tôi gọi ra ngoài. Nó giao một động cơ C nguyên bản với ABI sẵn cho C++ (libluxconsensus). Máy chủ Datastore là C++. Nên động cơ liên kết vào cùng một tiến trình — không sidecar, không cú nhảy mạng tới một bộ điều phối, không ngôn ngữ thứ hai lúc chạy.

Mối nối đã được chứng minh, trên máy trạng thái thật

Đây không phải phác thảo, và không còn là mô hình. Chúng tôi dựng một chương trình liên kết thư viện máy chủ ClickHouse thật (libdbms.a) và dẫn KeeperStateMachine<KeeperMemoryStorage> của sản xuất — đúng lớp mà ReplicatedMergeTree điều phối qua — hoàn toàn trên Quasar, NuRaft không có trên đường sắp thứ tự. Nó nằm trong cây Datastore tại src/Coordination/examples/keeper_quasar_poc.cpp và được dịch cùng chạy trên một máy Linux thật (aarch64, clang-21).

Luồng này trung thành với cách bộ điều phối dẫn NuRaft hôm nay — hai pha, preprocess khi một yêu cầu được nối thêm và commit khi đồng thuận chốt thứ tự của nó:

state_machine->preprocess(rfs, /*lock_mutex*/ true);     // append-time, pre-consensus (≙ nuraft pre_commit)
auto buf = IKeeperStateMachine::getZooKeeperLogEntry(rfs); // the real ZooKeeper log entry
lux_chain_add_block(chain, &blk);   // the entry rides Quasar (the slot raft_server occupies)
lux_consensus_process_vote(...);    // validators agree — no leader
lux_consensus_is_accepted(chain, id, &accepted);
state_machine->commit(height, *buf); // finality → the real KeeperStorage mutates, in order

Chạy trên một chuỗi điều phối mười yêu cầu của ReplicatedMergeTree — đăng ký bản sao, tăng số khối, bầu người dẫn đầu — nó tiền xử lý mọi yêu cầu, sắp chúng qua Quasar, chốt, commit vào KeeperStorage thật, và khẳng định cây kết quả đúng hoàn toàn, mỗi yêu cầu áp một lần, theo thứ tự đồng thuận:

== REAL Keeper state machine reached consensus on Quasar — zero Raft, zero ZK ensemble ==

Bên dưới là bản demo C-ABI tối thiểu (pkg/c/examples/cpp_consumer.cpp, make test-cpp) liên kết libluxconsensus và chốt một khối — cùng động cơ, không phụ thuộc ClickHouse. Cả hai tái lập được; ví dụ Datastore là tùy chọn (-DENABLE_EXAMPLES=1 -DLUXCONSENSUS_DIR=...) và không bao giờ thuộc một bản dựng thường.

Ánh xạ sang Keeper từng cặp một:

Keeper / NuRaft hôm nayNguyên bản trên Quasar
nuraft::raft_server sắp thứ tự nhật kýlux_chain_t sắp thứ tự nhật ký
KeeperLogStore / ChangelogNhật ký DAG của Quasar
Bầu người dẫn đầu của Raftbỏ phiếu tin cậy, không người dẫn đầu
state_machine->commit(idx, data)cùng một lời gọi, bắn khi is_accepted
chữ ký cổ điển, người dẫn đầu theo nhiệm kỳ cố địnhchữ ký ML-DSA, không người dẫn đầu
túc số ZK/Keeper riêng để vận hànhđồng thuận trong tiến trình, trong máy chủ

KeeperStateMachine::commit là điểm nối. NuRaft gọi nó hôm nay; trình dẫn Quasar gọi đúng phương thức đó ngày mai. Máy trạng thái không phân biệt được — đúng tính chất khiến đây là một lần đổi, không phải viết lại.

Vì sao điều này quan trọng hơn "hậu lượng tử"

  • Không người dẫn đầu. Raft có một người dẫn đầu được bầu mỗi nhiệm kỳ; khi người đó hỏng, ghi dừng cho đến khi bầu lại. Thỏa thuận không người dẫn đầu của Quasar bỏ sự phụ thuộc đầu hàng đó.
  • Không túc số thứ hai để chạy. Điều phối không còn là một hệ thống riêng mà bạn phải cấp, theo dõi, và sao lưu. Nó chính là máy chủ.
  • Hậu lượng tử nhờ cách dựng. Chữ ký bảo vệ thỏa thuận là ML-DSA, không phải đường cong cổ điển, nên một đối thủ lượng tử trong tương lai không thể giả mạo thông điệp đồng thuận.
  • Một câu chuyện vận chuyển. Nó ghép với phần còn lại của hướng đi — TCP/HTTP nguyên bản bây giờ, ZAP tiếp theo, và cùng các nguyên thủy Lux mà các chuỗi đang dùng.

Tình trạng thật

Kiến trúc ở trên là thật, và phép chứng minh giờ chạy trên KeeperStateMachine của sản xuất — không phải một mô hình — được dựng và đạt trên một máy Linux thật. Phần còn lại là lần đổi bên trong động cơ: đưa hậu phương đồng thuận Quasar vào trong KeeperServer cạnh NuRaft, đặt nó làm mặc định, rồi mang phần còn lại mà KeeperServer làm — ảnh chụp, phục hồi, hết hạn phiên, cấu hình lại — lên nó với cả bộ thử Coordination xanh. Đó là việc thật, và chúng tôi sẽ không nói Raft đã biến mất vào ngày chứng minh được đường commit. Chúng tôi nói mối nối đứng vững trước các kiểu thật, điểm nối là KeeperStateMachine::commit, và đó là toàn bộ canh bạc.

Khi nó vào cây, contrib/NuRaft/ và động cơ Raft rời khỏi cây. ZooKeeper API ở lại chừng nào nhân bản còn nói bằng nó. Đó là cách khai tử thành phần tiền lượng tử cuối cùng mà không đụng tới một MergeTree nào.

Bình luận

Đăng nhập bằng Hanzo ID để bình luận.

Đang tải bình luận…

Đọc tiếp