Hanzoのベータに参加すると、有料プランが50%オフになります

同じプロセスの中で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は、もともと分離できる二つのものが一つのデーモンに編み込まれたものだからです。

  1. ZooKeeper API — 逐次ノード、バージョン、ウォッチを備えた線形化可能なキーバリュー木です。ソースではこれがKeeperStorageで、KeeperStateMachineが包みます(src/Coordination/KeeperStateMachine.h、class IKeeperStateMachine : public nuraft::state_machine)。これが契約です。複製テーブルも、system.zookeeperのクエリも、リーダー選出も、みなこれを話します。

  2. 合意エンジン — 書き込み要求の流れを受け取り、ノードの定足数にその順序を合意させ、合意した順序で状態機械の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 / NuRaftQuasarネイティブ
nuraft::raft_serverがログを順序づけるlux_chain_tがログを順序づける
KeeperLogStore / ChangelogQuasarの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にも触れずに終わらせる方法はこれです。

コメント

コメントするには Hanzo ID でサインインしてください。

コメントを読み込み中…

続きを読む