同じプロセスの中でRaftを終わらせる:ZooKeeperの合意から直結するLux Quasarへ
Hanzo DatastoreがClickHouse Keeperの下にあるNuRaftエンジンをLux Quasarに置き換える仕組みです。後量子でリーダーのない合意をC++サーバへ直接リンクし、レプリケーションが話しているZooKeeperのAPIはそのまま残します。

このページの内容
Hanzo Datastoreは今日、複製テーブルをClickHouseと同じやり方で調整します。サーバプロセスの中でRaftを動かす、埋め込みのZooKeeper互換Keeperです。動きます。そしてこれはスタックに残る最後の、古典的でリーダー依存の、量子以前の部品でもあります。この記事はそれをどう終わらせるか、そして「ZKを終わらせる」が複製の書き換えではない理由です。
Keeperをほどく:APIとエンジン
「ZooKeeperを置き換える」と聞くと、あらゆるReplicated*MergeTreeに手を入れる想像をしがちです。その必要はありません。ClickHouse Keeperは、もともと分離できる二つのものが一つのデーモンに編み込まれたものだからです。
-
ZooKeeper API — 逐次ノード、バージョン、ウォッチを備えた線形化可能なキーバリュー木です。ソースではこれが
KeeperStorageで、KeeperStateMachineが包みます(src/Coordination/KeeperStateMachine.h、class IKeeperStateMachine : public nuraft::state_machine)。これが契約です。複製テーブルも、system.zookeeperのクエリも、リーダー選出も、みなこれを話します。 -
合意エンジン — 書き込み要求の流れを受け取り、ノードの定足数にその順序を合意させ、合意した順序で状態機械の
commit(log_idx, data)を呼びます。今日それはNuRaftです。KeeperServer::launchRaftServer(src/Coordination/KeeperServer.cpp)がnuraft::raft_server、asio_service、KeeperStateManager、KeeperLogStoreを組み立てます。
きれいな観察、Rich Hickeyの観察は、KeeperStateMachineがすでに汎用の合意インタフェースに対して書かれていることです(nuraft::state_machine:pre_commit、commit、rollback、スナップショット)。下にRaftがあることは知らず、気にもしません。エンジンは交換できる値であり、APIに溶接された場所ではありません。
したがって、状態機械は残し、エンジンを替える。 複製が依存するZooKeeper APIは手つかずで残ります。死ぬのはNuRaft、リーダー選出、そして別のRaft定足数を動かす必要です。
何が代わって入るか
エンジンはQuasarになります。Luxの、リーダーがなくDAGに基づく後量子の合意です。ここでのQuasarの仕事はRaftの仕事と同じで、ログの順序に合意し、エントリが確定したことを知らせます。違うのは合意の仕方です。フェイルオーバーする単一リーダーはなく、古典的署名の代わりにML-DSA署名を使い、固定タームの過半数ではなく信頼しきい値で確定します。
決定的なのは、Quasarが外へシェルで呼び出すGoサービスではないことです。C++向けのABIを備えたネイティブなCエンジンを届けます(libluxconsensus)。DatastoreのサーバはC++です。だからエンジンは同じプロセスの中へリンクします。サイドカーもなく、コーディネータへのネットワークホップもなく、実行時の第二言語もありません。
継ぎ目は証明済み、本物の状態機械に対して
これはスケッチではなく、もはや模型でもありません。ClickHouseサーバライブラリを本物のままリンクし(libdbms.a)、本番のKeeperStateMachine<KeeperMemoryStorage>を駆動するプログラムを作りました。ReplicatedMergeTreeが調整に使うのとまったく同じクラスで、順序付けの経路にNuRaftはどこにもありません。Datastoreツリーのsrc/Coordination/examples/keeper_quasar_poc.cppにあり、本物のLinuxホストでビルドして実行します(aarch64、clang-21)。
流れは、ディスパッチャが今日NuRaftを駆動する仕方に忠実です。二相で、要求が追記されるときがpreprocess、合意がその順序を確定するときがcommitです。
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
十件のReplicatedMergeTree調整列、レプリカ登録、ブロック番号の繰り上げ、リーダー選出に対して走らせると、各要求を前処理し、Quasarで順序を付け、確定し、本物のKeeperStorageへコミットし、結果の木が合意順に一度ずつ適用されて正確だと確かめます。
== REAL Keeper state machine reached consensus on Quasar — zero Raft, zero ZK ensemble ==
その下には最小のC ABIデモがあります(pkg/c/examples/cpp_consumer.cpp、make test-cpp)。libluxconsensusをリンクして単一ブロックを確定します。同じエンジンで、ClickHouseへの依存はありません。どちらも再現できます。Datastoreの例はオプトインで(-DENABLE_EXAMPLES=1 -DLUXCONSENSUS_DIR=...)、通常のビルドには入りません。
Keeperへ一対一で対応づけます。
| 今日のKeeper / NuRaft | Quasarネイティブ |
|---|---|
nuraft::raft_serverがログを順序づける | lux_chain_tがログを順序づける |
KeeperLogStore / Changelog | QuasarのDAGログ |
| Raftのリーダー選出 | リーダーのない信頼投票 |
state_machine->commit(idx, data) | 同じ呼び出しをis_acceptedで発火 |
| 古典的署名、固定タームのリーダー | ML-DSA署名、リーダーなし |
| 運用するための別のZK/Keeper定足数 | プロセス内、サーバ内の合意 |
KeeperStateMachine::commitが接合点です。今日はNuRaftが呼び、明日はQuasarのドライバが同じメソッドを呼びます。状態機械は違いを見分けられません。まさにこの性質が、書き換えではなく交換だという理由です。
「後量子」を超えてこれが重要な理由
- リーダーがない。 Raftはタームごとに選ばれたリーダーが一人で、その障害は再選出まで書き込みを止めます。Quasarのリーダーなし合意は、その行列先頭への依存を除きます。
- 動かす第二の定足数がない。 調整は、用意し監視しバックアップする別システムではなくなります。それがサーバです。
- 構造として後量子。 合意を守る署名は古典曲線ではなくML-DSAなので、将来の量子の敵対者は合意メッセージを偽造できません。
- トランスポートは一つの話。 残りの方向と組み合います。今はネイティブなTCP/HTTP、次はZAP、そしてチェーンが使うのと同じLuxのプリミティブです。
正直な現状
上のアーキテクチャは実在し、証明は今や模型ではなく本番のKeeperStateMachineに対して、本物のLinuxホスト上でビルドされ通っています。残るのはエンジン内の交換です。NuRaftと並べてKeeperServerの内側にQuasarの合意バックエンドを入れ、それを既定にし、それからKeeperServerが行う残り、スナップショット、復旧、セッション期限、再構成を、Coordinationのテスト一式を緑にしたまま載せます。これは本物の仕事です。コミット経路を証明した日にRaftが消えたとは言いません。継ぎ目は本物の型に対して持ち、接合点はKeeperStateMachine::commitであり、それが勝負のすべてだと言います。
それが入ったとき、contrib/NuRaft/とRaftエンジンはツリーを去ります。ZooKeeper APIは、複製がそれを話すあいだ残ります。最後の量子以前の部品を、一つのMergeTreeにも触れずに終わらせる方法はこれです。
- Datastore: github.com/hanzoai/datastore
- Luxの合意: github.com/luxfi/consensus
続きを読む

本日公開する Hanzo Datastore:ポスト量子時代の分析に備えた列指向 OLAP エンジン
ClickHouse 由来の列指向ウェアハウスです。Hanzo S3 上でストレージとコンピュートを分離して組み直し、プロファイルガイド最適化とリンク時最適化で常駐メモリをおよそ半分にし、gRPC を外したうえで、リーダー不要のポスト量子コーディネーションへ向かう道を開いています。

ルーターがレジストリである
Hanzo Cloud にチェックインされた OpenAPI ファイルはない。生きているルート表がソースであり、三通りに射影され、どの射影がずれても全単射のテストがビルドを落とす。963 パスにわたる 1,362 操作が、リクエスト時にプロセスごとに生成される。

Jin 2.0: The Next Generation of Multimodal AI
Announcing Jin 2.0, a major upgrade to our unified multimodal AI architecture with expanded capabilities and improved performance.