Eliminare Raft: dal consenso ZooKeeper a Lux Quasar, in modo nativo
Come Hanzo Datastore sostituisce il motore NuRaft sotto ClickHouse Keeper con Lux Quasar — consenso post-quantistico senza leader, collegato direttamente nel server C++ — e tiene l'API ZooKeeper che la replica parla.

In questa pagina
Hanzo Datastore coordina oggi le tabelle replicate come fa ClickHouse: un Keeper compatibile con ZooKeeper, incorporato, che esegue Raft dentro il processo del server. Funziona. È anche l'ultimo componente classico, con leader e pre-quantistico, dello stack. Questo articolo racconta come lo eliminiamo — e perché «uccidere ZK» non significa riscrivere la replica.
Districare Keeper: API contro motore
L'istinto, sentendo «sostituire ZooKeeper», è immaginare di dover toccare ogni Replicated*MergeTree. Non devi farlo, perché ClickHouse Keeper è già due cose separabili intrecciate in un solo demone:
-
L'API ZooKeeper — un albero chiave-valore linearizzabile, con nodi sequenziali, versioni e watches. Nel sorgente questo è
KeeperStorage, avvolto daKeeperStateMachine(src/Coordination/KeeperStateMachine.h,class IKeeperStateMachine : public nuraft::state_machine). Questo è il contratto. Ogni tabella replicata, ogni querysystem.zookeeper, ogni elezione del leader lo parla. -
Il motore di consenso — ciò che prende un flusso di richieste di scrittura, ottiene che un quorum di nodi si accordi sul loro ordine e poi chiama
commit(log_idx, data)sulla macchina a stati in quell'ordine concordato. Oggi è NuRaft:KeeperServer::launchRaftServer(src/Coordination/KeeperServer.cpp) costruisce unnuraft::raft_server, unasio_service, unKeeperStateManagere unKeeperLogStore.
L'osservazione pulita — quella di Rich Hickey — è che KeeperStateMachine è già scritta contro l'interfaccia di consenso generica (nuraft::state_machine: pre_commit, commit, rollback, snapshot). Non sa, e non le importa, che sotto ci sia Raft. Il motore è un valore che puoi sostituire, non un punto saldato all'API.
Quindi: tieni la macchina a stati, sostituisci il motore. L'API ZooKeeper da cui dipende la replica sopravvive intatta. Muoiono NuRaft, l'elezione del leader e l'obbligo di eseguire un quorum Raft separato.
Che cosa lo sostituisce
Il motore diventa Quasar — il consenso senza leader, basato su un DAG e post-quantistico di Lux. Il lavoro di Quasar qui è identico a quello di Raft: accordarsi sull'ordine di un log e segnalare quando una voce è finale. La differenza sta in come ci si accorda — nessun leader unico su cui fare failover, firme ML-DSA al posto di quelle classiche, e una finalità a soglia di confidenza anziché una maggioranza di un termine fisso.
Il punto decisivo: Quasar non è un servizio Go verso cui lanciamo un processo. Porta un motore C nativo con un'ABI pronta per C++ (libluxconsensus). Il server Datastore è C++. Il motore si collega quindi nello stesso processo — niente sidecar, niente salto di rete verso un coordinatore, niente seconda lingua a runtime.
La giuntura è dimostrata — contro la vera macchina a stati
Non è uno schizzo, e non è più un modello. Abbiamo costruito un programma che collega la libreria reale del server ClickHouse (libdbms.a) e guida la KeeperStateMachine<KeeperMemoryStorage> di produzione — la classe esatta attraverso cui si coordina ReplicatedMergeTree — interamente su Quasar, con NuRaft fuori dal percorso di ordinamento. Vive nell'albero Datastore in src/Coordination/examples/keeper_quasar_poc.cpp e si compila ed esegue su un host Linux reale (aarch64, clang-21).
Il flusso è fedele a come il dispatcher guida NuRaft oggi — due fasi, preprocess quando una richiesta viene accodata e commit quando il consenso fissa il suo ordine:
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
Eseguito contro una sequenza di coordinamento ReplicatedMergeTree di dieci richieste — registrazione della replica, incrementi del numero di blocco, elezione del leader — preprocessa ogni richiesta, le ordina tramite Quasar, finalizza, fa commit nel KeeperStorage reale e verifica che l'albero risultante sia esattamente corretto, applicato una volta ciascuno, nell'ordine del consenso:
== REAL Keeper state machine reached consensus on Quasar — zero Raft, zero ZK ensemble ==
Sotto c'è la dimostrazione minima dell'ABI C (pkg/c/examples/cpp_consumer.cpp, make test-cpp), che collega libluxconsensus e finalizza un singolo blocco — lo stesso motore, senza la dipendenza da ClickHouse. Entrambe sono riproducibili; l'esempio Datastore è facoltativo (-DENABLE_EXAMPLES=1 -DLUXCONSENSUS_DIR=...) e non entra mai in una build normale.
Mappalo su Keeper, uno a uno:
| Keeper / NuRaft oggi | Nativo Quasar |
|---|---|
nuraft::raft_server ordina il log | lux_chain_t ordina il log |
KeeperLogStore / Changelog | il log DAG di Quasar |
| elezione del leader Raft | voto di confidenza senza leader |
state_machine->commit(idx, data) | la stessa chiamata, innescata su is_accepted |
| firme classiche, leader a termine fisso | firme ML-DSA, nessun leader |
| un quorum ZK/Keeper separato da operare | consenso nel processo, nel server |
KeeperStateMachine::commit è il punto di giunzione. NuRaft lo chiama oggi; il driver Quasar chiama domani il metodo identico. La macchina a stati non può vedere la differenza — ed è esattamente la proprietà che ne fa uno scambio e non una riscrittura.
Perché conta oltre il «post-quantistico»
- Nessun leader. Raft ha un solo leader eletto per termine; il suo guasto blocca le scritture fino alla rielezione. L'accordo senza leader di Quasar toglie quella dipendenza di testa di linea.
- Nessun secondo quorum da far girare. Il coordinamento smette di essere un sistema a parte che provvedi, sorvegli e di cui fai il backup. È il server.
- Post-quantistico per costruzione. Le firme che proteggono l'accordo sono ML-DSA, non curve classiche, così un avversario quantistico futuro non può falsificare i messaggi di consenso.
- Una sola storia di trasporto. Si compone con il resto della direzione — TCP/HTTP nativo adesso, ZAP dopo, e le stesse primitive Lux che usano le catene.
Stato onesto
L'architettura sopra è reale, e la prova ora gira contro la KeeperStateMachine di produzione — non un modello —, compilata e verde su un host Linux reale. Quello che resta è lo scambio dentro il motore: introdurre il backend di consenso Quasar dentro KeeperServer, accanto a NuRaft, renderlo la scelta predefinita e poi portarci il resto di ciò che fa KeeperServer — snapshot, ripristino, scadenza di sessione, riconfigurazione — con l'intera suite di test Coordination verde. È lavoro vero, e non ti diremo che Raft è sparito il giorno in cui abbiamo provato il percorso di commit. Ti diciamo che la giuntura regge contro i tipi reali, che il punto di giunzione è KeeperStateMachine::commit, e che lì si gioca tutta la partita.
Quando atterra, contrib/NuRaft/ e il motore Raft escono dall'albero. L'API ZooKeeper resta finché la replica la parla. È così che si elimina l'ultimo componente pre-quantistico senza toccare un solo MergeTree.
- Datastore: github.com/hanzoai/datastore
- Consenso Lux: github.com/luxfi/consensus
Leggi di più

Vi presentiamo Hanzo Datastore: un motore OLAP pronto per il post-quantistico
Un magazzino colonnare derivato da ClickHouse, ricostruito intorno alla separazione tra archiviazione e calcolo su Hanzo S3, ottimizzato con i profili e in fase di linking fino a circa metà della memoria, con gRPC rimosso e una via verso il coordinamento post-quantistico senza leader.

Il router è il registro
Hanzo Cloud non ha alcun file OpenAPI versionato. La tabella di route viva è la fonte, proiettata in tre modi, e un test di biiezione fa fallire la build se una proiezione deriva. 1,362 operazioni su 963 path, generate per processo al momento della richiesta.

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.