[ConfigNode] Fix RegionGroup creation race with database deletion#18273
Open
CRZbulabula wants to merge 1 commit into
Open
[ConfigNode] Fix RegionGroup creation race with database deletion#18273CRZbulabula wants to merge 1 commit into
CRZbulabula wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens ConfigNode RegionGroup allocation against races with database deletion by introducing a per-database lifecycle generation fence, validating CreateRegionGroupsPlan batches before mutation, and serializing lifecycle-changing procedures with database-scoped locks. It also adds compensation procedures to clean up Region replicas created on DataNodes when persistence is rejected, and extends snapshot/procedure/plan serialization to remain compatible with pre-generation data.
Changes:
- Introduce database lifecycle generations and propagate them through allocation plans, persistence validation, and
PartitionInfosnapshots. - Add database-level lifecycle locks (including atomic multi-database acquisition) to serialize
CreateRegionGroupsProcedureandDeleteDatabaseProcedure. - Add targeted unit tests for rejection/compensation, atomic validation, ID advancement on rejected plans, and serialization compatibility.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/CreateRegionGroupsProcedureTest.java | Adds tests for persist rejection cleanup and mutual exclusion between create/delete database lifecycle locks. |
| iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java | Adds tests for pre-deleted/missing database rejection, stale plan fencing after recreation, atomic batch validation, and region ID advancement. |
| iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java | Adds SerDe coverage for CreateRegionGroupsPlan generation map and updates procedure SerDe expectations. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/scheduler/LockQueue.java | Adds isIdle() to support removing unused per-database lock queues. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java | Moves to AbstractDatabaseProcedure and declares database name(s) for lifecycle locking. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/CreateRegionGroupsProcedure.java | Adds pre-validation, persists generation metadata, and submits cleanup procedures on persistence rejection. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/AbstractDatabaseProcedure.java | New base procedure that holds exclusive lifecycle locks for its database set until completion. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java | Adds per-database lock map and atomic multi-lock acquisition/release APIs; exposes plan validation. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java | Adds generation tracking, plan validation, snapshot format changes, and advances region group ID high-water mark on rejected plans. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/DatabasePartitionTable.java | Stores immutable database generation and includes it in equality/hash. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionManager.java | Exposes generation and plan validation to higher-level components. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/balancer/RegionBalancer.java | Records current database generation into allocation plans. |
| iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/write/region/CreateRegionGroupsPlan.java | Adds generation map + SerDe support with backward compatibility. |
| iotdb-core/confignode/src/main/i18n/zh/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java | Adds localized log/message constants for CreateRegionGroupsPlan rejection reasons. |
| iotdb-core/confignode/src/main/i18n/en/org/apache/iotdb/confignode/i18n/ConfigNodeMessages.java | Adds localized log/message constants for CreateRegionGroupsPlan rejection reasons. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+249
to
+252
| final long expectedGeneration = plan.getDatabaseGeneration(database); | ||
| final long currentGeneration = databasePartitionTable.getDatabaseGeneration(); | ||
| if (plan.isDatabaseGenerationSet(database) && expectedGeneration != currentGeneration) { | ||
| LOGGER.warn( |
Comment on lines
1085
to
+1088
| // serialize nextRegionGroupId | ||
| ReadWriteIOUtils.write(SNAPSHOT_WITH_DATABASE_GENERATION_MAGIC, bufferedOutputStream); | ||
| ReadWriteIOUtils.write(nextRegionGroupId.get(), bufferedOutputStream); | ||
| ReadWriteIOUtils.write(nextDatabaseGeneration.get(), bufferedOutputStream); |
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
CreateRegionGroupsProcedurecould race withDeleteDatabaseProcedure. If the database partition table had already been removed when a replicatedCreateRegionGroupsPlanwas applied,PartitionInfo#createRegionGroupstreated the database as not pre-deleted and dereferenced a missingDatabasePartitionTable, causing an NPE in the ConfigRegion state machine.Simply skipping a missing database is unsafe because Region replicas may already have been created on DataNodes, and a delayed plan could be applied to a later database that reuses the same name.
This PR:
PartitionInfosnapshots;CreateRegionGroupsPlanbatch before mutation and returns explicit statuses for missing, pre-deleted, or generation-mismatched databases;CreateRegionGroupsProcedureandDeleteDatabaseProcedureagainst each other with database-level lifecycle locks, including atomic lock acquisition for multi-database plans;RemoveRegionGroupProcedurecompensation for replicas that were created on DataNodes when RegionGroup persistence is rejected;Tests
The added tests cover:
Validation performed:
The targeted test run completed with 121 tests and no failures. Both full-reactor locale builds completed successfully.
This PR has:
Key changed/added classes
PartitionInfoDatabasePartitionTableCreateRegionGroupsPlanCreateRegionGroupsProcedureDeleteDatabaseProcedureAbstractDatabaseProcedure