Repository navigation
[Feature] Add asynchronous bucket refresh mechanism for dynamic bucket mode #6389
Copy link
Copy link
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
In dynamic bucket mode, when buckets fill up and reach their target capacity, the assigner cannot detect that previously full buckets may have become available again
after compaction or data deletion.
This causes the system to continuously create new buckets even when existing buckets have free space, leading to:
- Unnecessary bucket growth
- Increased metadata overhead
- Suboptimal resource utilization
Root Cause
The PartitionIndex maintains an in-memory map (nonFullBucketInformation) of buckets with available space. However:
- When a bucket fills up, it's removed from this map
- Compaction or deletions may free space in these "full" buckets
- The assigner has no mechanism to rediscover these freed buckets
- Result: System keeps creating new buckets indefinitely
Proposed Solution
Add an asynchronous bucket refresh mechanism that:
Trigger Conditions
- Refresh triggers when a bucket's row count reaches
(target-row-num - threshold) - Example: With
target-row-num=1,000,000andthreshold=100,000, refresh triggers at 900,000 rows - This provides early warning before running out of available buckets
Architecture
- Async Execution: Uses
CompletableFuturewith dedicated thread pool - Thread Pool: Unbounded queue with 4 core / 12 max threads (I/O bound operations)
- Per-Partition: Each partition refreshes independently (handles data skew)
- Timeout: 5-minute timeout per refresh operation
- Thread-Safe: Uses
putIfAbsent()to avoid race conditions
Memory Efficiency
- Queue is unbounded but safe: ~400 bytes per task
- With 500 partitions: max ~200KB memory footprint
- Tasks are infrequent (24h default interval) and process quickly (30-60s)
Configuration Options
dynamic-bucket.empty-bucket-threshold (default: -1)
- Threshold in rows before triggering refresh
- When bucket reaches
(target-row-num - threshold), trigger refresh - Set to
-1to disable feature (backward compatible) - Recommended: 10-20% of
dynamic-bucket.target-row-num
dynamic-bucket.min-refresh-interval (default: 24 hours)
- Minimum time between refresh operations per partition
- Prevents excessive I/O overhead from frequent disk scans
- Longer intervals recommended for systems with many partitions (500+)
Implementation Details
Modified Files
PartitionIndex.java: Core refresh logic with async executorHashBucketAssigner.java: Pass configuration parametersCoreOptions.java: Add two new configuration optionsBucketProcessor.scala: Spark integrationHashBucketAssignerOperator.java: Flink integrationHashBucketAssignerTest.java: 5 new comprehensive tests
Key Features
- Backward Compatible: Disabled by default (threshold = -1)
- Data Skew Friendly: Works independently per partition
- Production Safe: Unbounded queue ensures no task rejection
- Well Tested: 15/15 tests pass including 5 new tests
Testing
New tests cover:
testRefreshTriggeredWhenBucketNearFull: Verify refresh triggers at thresholdtestRefreshDisabledWhenThresholdIsNegative: Backward compatibilitytestRefreshRespectsMinimumInterval: Interval enforcementtestRefreshWithMultiplePartitionsDataSkew: Data skew handlingtestRefreshDiscoversFreedBucketsAfterCompaction: Main use case
All existing tests continue to pass.
Benefits
- ✅ Reduces unnecessary bucket creation
- ✅ Better resource utilization
- ✅ Handles data skew (per-partition refresh)
- ✅ Low overhead (configurable intervals)
- ✅ Production safe (unbounded queue, no task rejection)
- ✅ Backward compatible (disabled by default)
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
RaguCS commentedon Oct 17, 2025
I'd like to take over this enhancement and start working on implementing the asynchronous bucket refresh mechanism for dynamic bucket mode.
My plan:
Review the current PartitionIndex logic and how dynamic buckets are managed.
Implement the proposed async refresh logic using CompletableFuture to periodically scan and update available buckets.
Add configuration options for:
dynamic-bucket.empty-bucket-thresholddynamic-bucket.refresh-intervalOnce the initial implementation is ready, I’ll open a PR for review and feedback.
irodriguezclaveria commentedon Oct 17, 2025
Hi @RaguCS ,
Thanks for offering to take this on and for the very clear and solid plan.
My PR has an almost-finished implementation of this feature (there are a lot of things pending as the tests). However, your plan looks great, and I agree it's the right direction for the project.
If you'd like to lead the implementation from here, please feel free to use any code or ideas from my PR. I'm happy to close it in favor of your new one to avoid duplicated efforts.
Just let me know how you'd like to proceed!
Cheers,
RaguCS commentedon Oct 17, 2025
Hi @irodriguezclaveria ,
Thanks a lot for the kind message and for sharing your progress on this feature! I really appreciate your openness and collaboration.
Your existing PR and implementation details will be very helpful — I’ll make sure to review and reuse parts of it where appropriate to keep consistency and avoid duplicated work.
I’d also love to collaborate and discuss ideas as the work progresses.
If you’re open to it, feel free to reach out to me via email at ragusfc143@gmail.com
— it’d be great to exchange thoughts or get your guidance when I hit any blockers.
Cheers,
Ragu ☕
irodriguezclaveria commentedon Oct 17, 2025
Hey @RaguCS ,
Awesome, thanks for reaching out! So glad you found the PR useful.
Sounds great, I'll drop you an email. Happy to help out if you hit any roadblocks or just want to chat about the approach.
RaguCS commentedon Oct 17, 2025
🙌 Thanks!
Hey @irodriguezclaveria ,
Awesome, thanks a lot! Really appreciate your willingness to help and collaborate.
I’ll keep you posted on my progress and will definitely reach out if I run into any roadblocks or want to discuss the design further.
Looking forward to working together on this! 🚀
[core] Add async bucket refresh for dynamic bucket mode
[core] Add async bucket refresh for dynamic bucket mode