Distributed Consensus and Recovery#
HugeGraph's storage layer (hugegraph-store) achieves distributed data consistency and durability through Raft-based state machine replication built on the Apache SoFA JRaft library, combined with RocksDB checkpoint-based snapshots that include integrity verification before activation.
Architecture Overview#
Each partition of graph data is managed by a PartitionEngine , which owns a JRaft RaftGroupService and Node. All writes flow through the Raft consensus protocol before being applied to the local RocksDB instance, ensuring all replicas maintain the same state.
Write Request
β
βΌ
PartitionEngine.addRaftTask()
β (serialized as RaftOperation)
βΌ
JRaft Node.apply()
β (replicated to quorum)
βΌ
PartitionStateMachine.onApply()
β (applied by leader and all followers)
βΌ
BusinessHandler / DataManager (RocksDB write)
Core Components#
PartitionEngine#
PartitionEngine is the orchestration layer for each Raft group (one per partition). Key responsibilities:
- Initialization: Configures
NodeOptions(log path, metadata path, snapshot path, election/RPC timeouts) and starts aRaftGroupServiceper partition group . - Write path:
addRaftTask()serializes operations and callsNode.apply(). Only the current leader accepts tasks; followers reject withNOT_LEADER. - Error recovery: On
onError(), callsrestartRaftNode(), which shuts down and re-initializes theRaftGroupService. - Peer management:
changePeers()orchestrates the learner β follower promotion workflow: add as learner β wait for snapshot sync β promote to full peer. - Snapshot triggering:
doSnapshot()anddoSnapshotSync()invokeNode.snapshot()directly, gated by anAtomicBooleanto prevent concurrent snapshot operations.
PartitionStateMachine#
PartitionStateMachine extends JRaft's StateMachineAdapter. It:
- Applies log entries:
onApply()iterates committed log entries and dispatches each to registeredRaftTaskHandlerimplementations . Both leader (local call) and follower (deserialized byte array) paths are handled. - Saves snapshots:
onSnapshotSave()executes asynchronously under aReentrantLockto prevent concurrent saves, then delegates toSnapshotHandler. - Loads snapshots:
onSnapshotLoad()refuses to load on the leader , readsSnapshotMetato recover thecommittedIndex, then delegates toSnapshotHandler.
SnapshotHandler#
SnapshotHandler bridges JRaft's snapshot API and RocksDB:
- Save (
onSnapshotSave()): CallsbusinessHandler.saveSnapshot()to create a RocksDB checkpoint into<snapshotDir>/data, enumerates all files, and registers each with the JRaftSnapshotWriter. CRC64 checksums are computed for.sstand.logfiles β for files β€ 8 KB the full file is checksummed; for larger files only the head and tail 4 KB blocks are hashed. Ashould_not_loadmarker file is written to prevent the local node from redundantly reloading its own snapshot . - Load (
onSnapshotLoad()): Skips loading if theshould_not_loadflag is present , then callsbusinessHandler.loadSnapshot(), reloads partition metadata from the local DB, and replays any pending async tasks .
RocksDBSession β Checkpoint and Verification#
RocksDBSession implements the low-level checkpoint operations:
saveSnapshot(): Creates a RocksDBCheckpointat a_temppath, then atomically renames it to the final snapshot path. A read lock oncfHandleLockis held throughout.verifySnapshot(): Opens the snapshot in read-only mode (RocksDB.openReadOnly()) and validates that everyColumnFamilyHandleis non-null. Returnsfalseimmediately on any null handle orRocksDBException.loadSnapshot(): Under a write lock, hard-links (or copies) snapshot files to a_tempdirectory, callsverifySnapshot()on the temp path , and only on success atomically moves the verified directory to the final database path. This ensures a corrupt snapshot never replaces a healthy database.
Membership Changes and Replication#
New replicas join as learners first. The ReplicatorStateListener inner class monitors JRaft replicator state changes; when a learner transitions to ONLINE (snapshot fully transferred), it triggers any pending Change_Shard task to promote the learner to a full peer .
Log storage is backed by either RocksDBLogStorage or RocksDBSegmentLogStorage, selected via configuration .
Key Source Files#
| File | Purpose |
|---|---|
PartitionEngine.java | Raft group lifecycle, write path, peer management |
PartitionStateMachine.java | State machine: apply, snapshot save/load hooks |
SnapshotHandler.java | JRaft β RocksDB snapshot bridge, CRC64 checksums |
RocksDBSession.java | Checkpoint creation, read-only integrity verification, load |