Vladimir Rodionov created HBASE-30384:
-----------------------------------------

             Summary: Add dynamic cache sizing support for CacheEngine-based 
caches
                 Key: HBASE-30384
                 URL: https://issues.apache.org/jira/browse/HBASE-30384
             Project: HBase
          Issue Type: New Feature
          Components: BlockCache
            Reporter: Vladimir Rodionov
            Assignee: Vladimir Rodionov
             Fix For: 4.0.0-alpha-1


Add support for dynamically resizing CacheEngine-based caches so that the 
existing HeapMemoryManager functionality can operate with the new block cache 
architecture without depending on legacy ResizableBlockCache implementations.

Currently, HeapMemoryManager accepts a BlockCache and converts it to a 
ResizableBlockCache. For a CombinedBlockCache, it explicitly extracts the 
first-level cache:
{code:java}
private final ResizableBlockCache blockCache;

private ResizableBlockCache toResizableBlockCache(BlockCache blockCache) {
  if (blockCache instanceof CombinedBlockCache) {
    return ((CombinedBlockCache) blockCache).getFirstLevelCache();
  } else {
    return (ResizableBlockCache) blockCache;
  }
}
{code}
HeapMemoryManager then dynamically adjusts the cache size using:
{code:java}
blockCache.setMaxSize(newBlockCacheSize);
{code}
This creates a direct dependency on the legacy BlockCache hierarchy and on 
CombinedBlockCache topology details.

The new cache architecture uses CacheAccessService, CacheTopology, and 
CacheEngine. CacheEngine exposes getMaxSize() and cache usage information, but 
currently has no capability for changing the maximum cache size at runtime.

Dynamic resizing should be represented as an optional CacheEngine capability 
rather than adding setMaxSize() to every CacheEngine implementation.

Introduce a capability interface for cache engines that support runtime 
resizing, for example:
{code:java}
@InterfaceAudience.Private
public interface ResizableCacheEngine extends CacheEngine {

  /**
   * Changes the maximum size of this cache engine.
   *
   * @param maxSize new maximum cache size in bytes
   */
  void setMaxSize(long maxSize);
}
{code}
Native cache engines that support dynamic resizing, such as LruCacheEngine, 
should implement this interface.

HeapMemoryManager should be migrated to operate on the appropriate resizable 
CacheEngine rather than ResizableBlockCache. Selection of the cache engine to 
resize should use the cache topology rather than inspecting legacy 
CombinedBlockCache implementations.

For a tiered topology, HeapMemoryManager should resize the heap-resident 
first-level cache engine. For a single-tier topology, the engine should be 
resized when it implements ResizableCacheEngine.

The target architecture should be approximately:
{code:java}
HeapMemoryManager
        |
        v
CacheAccessService / CacheTopology
        |
        v
ResizableCacheEngine
        |
        v
setMaxSize(...)
{code}
instead of:
{code:java}
HeapMemoryManager
        |
        v
BlockCache
        |
        +-- CombinedBlockCache
        |       |
        |       v
        |   getFirstLevelCache()
        |
        v
ResizableBlockCache
        |
        v
setMaxSize(...)
{code}
Scope:
 * Introduce a CacheEngine capability for engines that support dynamic resizing.
 * Make LruCacheEngine implement the new resizing capability.
 * Preserve the existing LruCacheEngine setMaxSize() behavior.
 * Allow HeapMemoryManager to obtain the appropriate resizable engine from the 
new cache architecture.
 * Remove HeapMemoryManager's dependency on CombinedBlockCache topology 
inspection for CacheEngine-based configurations.
 * Update HeapMemoryManager to resize the selected CacheEngine through the new 
capability.
 * Preserve existing HeapMemoryManager cache statistics and tuning behavior.
 * Add tests for dynamically resizing a native LruCacheEngine.
 * Add tests for selecting the correct resizable engine in single-tier and 
tiered cache topologies.
 * Preserve compatibility with legacy BlockCache/ResizableBlockCache 
configurations during the migration where necessary.

Topology Behavior:

For SINGLE_TIER topology:
{code:java}
SINGLE
  |
  +-- if engine implements ResizableCacheEngine
          |
          v
      setMaxSize(...)
{code}
For TIERED_EXCLUSIVE and TIERED_INCLUSIVE topologies:
{code:java}
L1 --> resize if it implements ResizableCacheEngine
L2 --> unchanged
{code}
Dynamic heap-memory tuning should not resize L2 merely because it is part of 
the same cache topology.

Out of Scope:
 * General cache configuration-change propagation through CacheAccessService.
 * Migration of BucketCache to a native CacheEngine implementation.
 * Changes to the HeapMemoryTuner algorithm or tuning policy.
 * Changes to cache admission, placement, promotion, or eviction policy.
 * Making every CacheEngine dynamically resizable.
 * RegionServer ownership migration from BlockCache to CacheAccessService 
except for changes necessary to allow HeapMemoryManager to access the 
appropriate CacheEngine.

Acceptance Criteria:
 * A native LruCacheEngine can be resized at runtime through the new 
CacheEngine resizing capability.
 * HeapMemoryManager can dynamically resize a native LruCacheEngine without 
requiring an LruBlockCache or ResizableBlockCache wrapper.
 * For a tiered topology, HeapMemoryManager resizes the L1 engine and does not 
resize L2.
 * For a single-tier topology, HeapMemoryManager resizes the SINGLE engine when 
that engine supports dynamic resizing.
 * HeapMemoryManager no longer needs to inspect CombinedBlockCache in the 
native CacheEngine path.
 * Cache engines that do not support dynamic resizing are not required to 
implement a no-op setMaxSize() method.
 * Existing heap-memory tuning behavior remains compatible.
 * Existing relevant HeapMemoryManager and block-cache tests continue to pass.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to