Skip to content

[Feature] Add asynchronous bucket refresh mechanism for dynamic bucket mode #6389

Open

Description

@irodriguezclaveria

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:

  1. When a bucket fills up, it's removed from this map
  2. Compaction or deletions may free space in these "full" buckets
  3. The assigner has no mechanism to rediscover these freed buckets
  4. 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,000 and threshold=100,000, refresh triggers at 900,000 rows
  • This provides early warning before running out of available buckets

Architecture

  • Async Execution: Uses CompletableFuture with 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 -1 to 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 executor
  • HashBucketAssigner.java: Pass configuration parameters
  • CoreOptions.java: Add two new configuration options
  • BucketProcessor.scala: Spark integration
  • HashBucketAssignerOperator.java: Flink integration
  • HashBucketAssignerTest.java: 5 new comprehensive tests

Key Features

  1. Backward Compatible: Disabled by default (threshold = -1)
  2. Data Skew Friendly: Works independently per partition
  3. Production Safe: Unbounded queue ensures no task rejection
  4. Well Tested: 15/15 tests pass including 5 new tests

Testing

New tests cover:

  • testRefreshTriggeredWhenBucketNearFull: Verify refresh triggers at threshold
  • testRefreshDisabledWhenThresholdIsNegative: Backward compatibility
  • testRefreshRespectsMinimumInterval: Interval enforcement
  • testRefreshWithMultiplePartitionsDataSkew: Data skew handling
  • testRefreshDiscoversFreedBucketsAfterCompaction: 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)

Activity

  1. RaguCS commented on Oct 17, 2025

    @RaguCS

    I'd like to take over this enhancement and start working on implementing the asynchronous bucket refresh mechanism for dynamic bucket mode.

    My plan:

    1. Review the current PartitionIndex logic and how dynamic buckets are managed.

    2. Implement the proposed async refresh logic using CompletableFuture to periodically scan and update available buckets.

    3. Add configuration options for:

    • dynamic-bucket.empty-bucket-threshold

    • dynamic-bucket.refresh-interval

    1. Write tests to verify that refreshed buckets are correctly reused and that the refresh operation doesn’t block assignment.

    Once the initial implementation is ready, I’ll open a PR for review and feedback.

  2. irodriguezclaveria commented on Oct 17, 2025

    @irodriguezclaveria
    ContributorAuthor

    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,

  3. RaguCS commented on Oct 17, 2025

    @RaguCS

    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 ☕

  4. irodriguezclaveria commented on Oct 17, 2025

    @irodriguezclaveria
    ContributorAuthor

    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.

  5. RaguCS commented on Oct 17, 2025

    @RaguCS

    🙌 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! 🚀

  6. added 2 commits that reference this issue on Mar 15, 2026
    bfe5286
    d463fc9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions