Gabung beta Hanzo dan dapatkan diskon 50% untuk setiap paket berbayar

Mematikan Raft: dari konsensus ZooKeeper ke Lux Quasar, tertaut secara native

Bagaimana Hanzo Datastore mengganti mesin NuRaft di bawah ClickHouse Keeper dengan Lux Quasar — konsensus pasca-kuantum tanpa pemimpin yang ditautkan langsung ke server C++ — sambil mempertahankan ZooKeeper API yang dipakai replikasi.

Di halaman ini

Hanzo Datastore mengoordinasikan tabel tereplikasi hari ini seperti yang dilakukan ClickHouse: Keeper tertanam yang kompatibel dengan ZooKeeper, menjalankan Raft di dalam proses server. Itu bekerja. Ia juga komponen klasik terakhir yang berbasis pemimpin dan pra-kuantum di tumpukan ini. Tulisan ini menjelaskan bagaimana kami mematikannya, dan mengapa "mematikan ZK" tidak berarti menulis ulang replikasi.

Memisahkan Keeper: API versus mesin

Naluri saat mendengar "mengganti ZooKeeper" adalah membayangkan menyentuh setiap Replicated*MergeTree. Anda tidak perlu melakukannya, karena ClickHouse Keeper sudah berupa dua hal yang dapat dipisah dan terjalin dalam satu daemon:

  1. ZooKeeper API — pohon kunci-nilai yang dapat diurutkan secara linear, dengan simpul berurutan, versi, dan watch. Di sumber, ini adalah KeeperStorage, dibungkus oleh KeeperStateMachine (src/Coordination/KeeperStateMachine.h, class IKeeperStateMachine : public nuraft::state_machine). Inilah kontrak. Setiap tabel tereplikasi, setiap kueri system.zookeeper, dan setiap pemilihan pemimpin berbicara dengannya.

  2. Mesin konsensus — hal yang mengambil aliran permintaan tulis, membuat kuorum simpul menyepakati urutannya, lalu memanggil commit(log_idx, data) pada mesin keadaan dalam urutan yang disepakati itu. Hari ini itu NuRaft: KeeperServer::launchRaftServer (src/Coordination/KeeperServer.cpp) membangun sebuah nuraft::raft_server, sebuah asio_service, sebuah KeeperStateManager, dan sebuah KeeperLogStore.

Pengamatan yang bersih, pengamatan Rich Hickey, adalah bahwa KeeperStateMachine sudah ditulis terhadap antarmuka konsensus yang generik (nuraft::state_machine: pre_commit, commit, rollback, snapshot). Ia tidak tahu dan tidak peduli bahwa Raft ada di bawahnya. Mesin adalah nilai yang dapat ditukar, bukan tempat yang dilas ke dalam API.

Jadi: pertahankan mesin keadaan, ganti mesinnya. ZooKeeper API yang diandalkan replikasi tetap utuh. Yang mati adalah NuRaft, pemilihan pemimpin, dan keharusan menjalankan kuorum Raft terpisah.

Apa yang menggantikannya

Mesin itu menjadi Quasar — konsensus tanpa pemimpin, berbasis DAG, dan pasca-kuantum dari Lux. Tugas Quasar di sini identik dengan tugas Raft: menyepakati urutan log dan memberi isyarat saat sebuah entri final. Bedanya ada pada cara menyepakati: tidak ada satu pemimpin untuk diambil alih saat gagal, tanda tangan ML-DSA alih-alih tanda tangan klasik, dan finalitas ambang keyakinan alih-alih mayoritas pada term yang tetap.

Yang terpenting, Quasar bukan layanan Go yang kami panggil lewat shell. Ia menghadirkan mesin C native dengan ABI yang siap untuk C++ (libluxconsensus). Server Datastore adalah C++. Jadi mesin tertaut ke dalam proses yang sama — tanpa sidecar, tanpa lompatan jaringan ke koordinator, tanpa bahasa kedua pada saat runtime.

Sambungannya terbukti, pada mesin keadaan yang sesungguhnya

Ini bukan sketsa, dan bukan lagi sebuah model. Kami membangun program yang menautkan pustaka server ClickHouse yang sesungguhnya (libdbms.a) dan menggerakkan KeeperStateMachine<KeeperMemoryStorage> produksi — kelas yang sama yang dilalui koordinasi ReplicatedMergeTree — sepenuhnya di atas Quasar, dengan NuRaft tidak ada di jalur pengurutan. Ia berada di pohon Datastore pada src/Coordination/examples/keeper_quasar_poc.cpp dan dibangun serta dijalankan pada host Linux yang sungguhan (aarch64, clang-21).

Alurnya setia pada cara dispatcher menggerakkan NuRaft hari ini — dua fase, preprocess saat permintaan ditambahkan dan commit saat konsensus memfinalkan urutannya:

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

Dijalankan terhadap urutan koordinasi sepuluh permintaan ReplicatedMergeTree — pendaftaran replika, kenaikan nomor blok, pemilihan pemimpin — ia mempraproses setiap permintaan, mengurutkannya lewat Quasar, memfinalkan, melakukan commit ke KeeperStorage yang sesungguhnya, dan menegaskan bahwa pohon yang dihasilkan tepat benar, masing-masing diterapkan sekali, dalam urutan konsensus:

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

Di bawahnya ada demonstrasi C-ABI minimal (pkg/c/examples/cpp_consumer.cpp, make test-cpp) yang menautkan libluxconsensus dan memfinalkan satu blok — mesin yang sama, tanpa ketergantungan ClickHouse. Keduanya dapat direproduksi; contoh Datastore bersifat ikut serta (-DENABLE_EXAMPLES=1 -DLUXCONSENSUS_DIR=...) dan tidak pernah menjadi bagian dari build normal.

Petakan ke Keeper satu lawan satu:

Keeper / NuRaft hari iniNative di Quasar
nuraft::raft_server mengurutkan loglux_chain_t mengurutkan log
KeeperLogStore / ChangelogLog DAG Quasar
Pemilihan pemimpin Raftvoting keyakinan tanpa pemimpin
state_machine->commit(idx, data)panggilan yang sama, dipicu pada is_accepted
tanda tangan klasik, pemimpin term tetaptanda tangan ML-DSA, tanpa pemimpin
kuorum ZK/Keeper terpisah untuk beroperasikonsensus di dalam proses, di dalam server

KeeperStateMachine::commit adalah titik sambung. NuRaft memanggilnya hari ini; penggerak Quasar memanggil metode yang sama besok. Mesin keadaan tidak dapat membedakannya — dan itulah sifat yang membuat ini pertukaran, bukan penulisan ulang.

Mengapa ini penting di luar "pasca-kuantum"

  • Tanpa pemimpin. Raft punya satu pemimpin terpilih tiap term; kegagalannya menahan penulisan sampai pemilihan ulang. Kesepakatan tanpa pemimpin dari Quasar menghapus ketergantungan di kepala antrean itu.
  • Tanpa kuorum kedua untuk dijalankan. Koordinasi berhenti menjadi sistem terpisah yang Anda sediakan, pantau, dan cadangkan. Ia adalah server itu sendiri.
  • Pasca-kuantum karena konstruksinya. Tanda tangan yang melindungi kesepakatan adalah ML-DSA, bukan kurva klasik, sehingga lawan kuantum di masa depan tidak dapat memalsukan pesan konsensus.
  • Satu cerita transport. Ia tersusun dengan sisa arah ini — TCP/HTTP native sekarang, ZAP berikutnya, dan primitif Lux yang sama yang dipakai rantai.

Status yang jujur

Arsitektur di atas nyata, dan buktinya kini berjalan pada KeeperStateMachine produksi — bukan pada model — dibangun dan lulus di host Linux yang sungguhan. Yang tersisa adalah pertukaran di dalam mesin: memperkenalkan backend konsensus Quasar di dalam KeeperServer di samping NuRaft, menjadikannya bawaan, lalu membawa sisa yang dilakukan KeeperServer — snapshot, pemulihan, kedaluwarsa sesi, rekonfigurasi — ke atasnya dengan seluruh rangkaian uji Coordination berwarna hijau. Itu kerja yang nyata, dan kami tidak akan mengatakan Raft sudah hilang pada hari kami membuktikan jalur commit. Kami mengatakan sambungan bertahan terhadap tipe yang sesungguhnya, titik sambungnya adalah KeeperStateMachine::commit, dan itulah seluruh pertaruhannya.

Saat itu mendarat, contrib/NuRaft/ dan mesin Raft meninggalkan pohon. ZooKeeper API tetap selama replikasi berbicara dengannya. Begitulah komponen pra-kuantum terakhir dimatikan tanpa menyentuh satu pun MergeTree.

Komentar

Masuk dengan Hanzo ID untuk berkomentar.

Memuat komentar…

Baca selengkapnya