Store Lifecycle Management#
The PD (Placement Driver) module coordinates the full lifecycle of HugeStore nodes β from initial registration through graceful shutdown β via two primary services: StoreNodeService and TaskScheduleService. Store state is persisted in RocksDB through StoreInfoMeta, and exposed over REST via StoreAPI.
State Machine#
A store progresses through these states (defined in Metapb.StoreState):
| State | Meaning |
|---|---|
Pending | Newly created node; heartbeats received but cluster not yet ready |
Up | Online and healthy; included in active-store set |
Offline | Missed heartbeat TTL; removed from active set by patrolStores |
Exiting | Graceful shutdown requested; migration in progress |
Tombstone | Fully decommissioned; registration denied |
Registration#
StoreNodeService.register() handles both first-time and re-registration:
- First-time: a random 64-bit
storeIdis generated bynewStoreNode(), the store is persisted with statePending. - Re-registration: if the store was
OfflineorUp, or appears ininitialStoreList, it transitions directly toUp. Other states land inPending. - Tombstone guard: stores in
Tombstonestate are rejected at registration time . - Duplicate detection: if the Raft address changed within
0.8ΓSTORE_HEART_BEAT_INTERVAL(24 s of the 30 s default), the registration is rejected as a probable duplicate .
Heartbeats & TTL-based Active Membership#
StoreNodeService.heartBeat() is the main keep-alive path:
- Every heartbeat calls
StoreInfoMeta.keepStoreAlive(), which writes the store's serialized proto under anactiveStorekey with a configurable TTL (pdConfig.store.keepAliveTimeout). - Active-store reads use
getInstanceListWithTTL(), which returns only entries whose TTL has not expired β so membership naturally shrinks when heartbeats stop. - A store in
Offlinestate that sends a heartbeat is automatically promoted back toUp. - A store in
Exitingstate that reportspartitionCount == 0is auto-promoted toTombstonevia heartbeat, signalling that all its replicas have migrated out .
TaskScheduleService.patrolStores() runs every 60 seconds and catches any Up/Unknown store that has silently disappeared from the active set, marking it Offline .
State Transitions via updateStore#
StoreNodeService.updateStore() is the controlled path for external state changes and reacts to each new state:
Exiting: removes the store from the active set if it was already inactive; triggersstoreTurnoff()to start shard reallocation .Offline: removes from active set immediately .Tombstone: removes from active set and callsstoreTurnoff(). Guarded: transition is blocked if it would drop active stores belowpdConfig.minStoreCount.Up: callskeepStoreAlive()and re-evaluates cluster health .
Every state change fires onStoreStatusChanged() , which notifies all registered StoreStatusListeners β including TaskScheduleService, which records the lastStoreTurnoffTime when a store goes Tombstone .
Shard Reallocation & Replica Migration#
storeTurnoff(store) iterates every ShardGroup that contains a shard on the departing store, removes that shard, and calls reallocShards():
reallocShardscomputes the desiredshardCountfrom config, adds or removes shards from active stores via modulo assignment, persists the newShardGroup, and firesConfChangeType.CONF_CHANGE_TYPE_ADJUSTto the affected partition so the Raft group reconfigures itself .TaskScheduleService.patrolPartitions()independently checks that every shard group matches the configured replica count and callsreallocShards()for any that don't .- Load balancing (
balancePartitionShard) is intentionally held for at least 30 minutes after the last store turn-off (TurnOffAndBalanceInterval) to allow replicas to stabilise before redistribution .
Cluster Health Check#
After every Up/heartbeat event, checkStoreStatus() verifies:
- Active store count β₯
pdConfig.minStoreCount(otherwiseCluster_Not_Ready). - For each shard group, more than half of its shards are on active stores (otherwise
Cluster_Not_Ready).
Shard group state changes propagate via updateShardGroupState() β updateClusterStatus() β ClusterStats .
REST API Entry Points#
StoreAPI exposes the lifecycle externally:
| Endpoint | Purpose |
|---|---|
GET /v1/stores | List all stores with state counts |
POST /v1/store/{storeId} | Manually set store state (e.g., trigger Exiting) |
DELETE /v1/store/{storeId} | Remove store metadata |
GET /v1/shardGroups | Inspect current shard group assignments |
GET /v1/balanceLeaders | Trigger leader rebalancing |
Key Source Files#
| File | Role |
|---|---|
StoreNodeService.java | Core lifecycle: registration, heartbeat, state transitions, shard realloc |
StoreInfoMeta.java | RocksDB persistence layer; TTL-based active-store membership |
TaskScheduleService.java | Background patrol (60 s), balance, partition patrol |
StoreAPI.java | REST API for operators / monitoring |
PartitionService.java | Raft conf-change dispatch, partition movement (source) |