[ 
https://issues.apache.org/jira/browse/HBASE-30384?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Vladimir Rodionov updated HBASE-30384:
--------------------------------------
    Description: 
h2. Description

The new block cache architecture represents cache implementations through 
{{CacheEngine}}, but
{{CacheEngine}} currently has no capability for changing the maximum cache size 
at runtime.

Dynamic cache sizing is required by HBase heap-memory tuning. In the legacy 
cache architecture this
capability is represented by {{ResizableBlockCache}} and {{setMaxSize(long)}}.

{{CombinedBlockCache}} also implements {{ResizableBlockCache}} and applies 
dynamic resizing to its
first-level cache only. This preserves the expected heap-memory tuning behavior 
for tiered legacy
caches.

The new cache architecture needs an equivalent capability so that native 
{{CacheEngine}}
implementations can participate in dynamic cache sizing after RegionServer 
cache ownership is
migrated to {{CacheAccessService}}.

Dynamic resizing should be represented as an optional cache engine 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.

This issue establishes the cache-engine resizing capability only. Migration of
{{HeapMemoryManager}} to the new cache architecture requires migration of 
{{HRegionServer}} cache
ownership from {{BlockCache}} to {{CacheAccessService}} and is therefore 
outside the scope of this
issue.

h2. Current Architecture

{{HeapMemoryManager}} is currently created by {{HRegionServer}} using the 
legacy {{BlockCache}}
instance.

Dynamic cache sizing therefore follows the legacy cache hierarchy:

{noformat}
HRegionServer
      |
      v
  BlockCache
      |
      v
HeapMemoryManager
      |
      v
ResizableBlockCache
      |
      v
 setMaxSize(...)
{noformat}

For {{CombinedBlockCache}}, the resizing operation applies to the first-level 
cache while the
second-level cache remains unchanged.

This behavior should remain unchanged until {{HRegionServer}} and 
{{HeapMemoryManager}} are migrated
to the new cache architecture.

h2. Target Capability

The new architecture should provide an equivalent optional resizing capability:

{noformat}
CacheEngine
    |
    v
ResizableCacheEngine
    |
    v
setMaxSize(...)
{noformat}

A cache engine that supports runtime resizing implements 
{{ResizableCacheEngine}}.

A cache engine that does not support dynamic resizing does not implement the 
interface and does not
need to provide a no-op {{setMaxSize()}} implementation.

h2. Proposed Changes

* Introduce {{ResizableCacheEngine}} as an optional {{CacheEngine}} capability.
* Make {{LruCacheEngine}} implement {{ResizableCacheEngine}}.
* Preserve the existing {{LruCacheEngine.setMaxSize(long)}} behavior.
* Preserve dynamic-resizing capability when legacy {{ResizableBlockCache}} 
implementations are
  adapted to {{CacheEngine}}, where applicable.
* Add tests for resizing a native {{LruCacheEngine}} through 
{{ResizableCacheEngine}}.
* Add tests for preservation of resizing capability through legacy cache 
adapters, where
  applicable.

h2. Future Integration

After {{HRegionServer}} cache ownership is migrated from {{BlockCache}} to
{{CacheAccessService}}, {{HeapMemoryManager}} can be migrated to operate on
{{ResizableCacheEngine}} instead of {{ResizableBlockCache}}.

At that point, selection of the cache engine participating in heap-memory 
tuning should preserve the
existing semantics:

* For a single-tier topology, resize the {{SINGLE}} engine when it implements
  {{ResizableCacheEngine}}.
* For a tiered topology, resize the heap-resident {{L1}} engine when it 
implements
  {{ResizableCacheEngine}}.
* {{L2}} should not be resized merely because it belongs to the same topology.

That integration is intentionally deferred to the 
RegionServer/{{CacheAccessService}} ownership
migration.

h2. Out of Scope

* Changes to {{HRegionServer}} cache ownership.
* Migration of {{HeapMemoryManager}} from 
{{BlockCache}}/{{ResizableBlockCache}} to
  {{CacheAccessService}}/{{ResizableCacheEngine}}.
* Changes to {{CombinedBlockCache}} resizing behavior.
* Changes to the {{HeapMemoryTuner}} algorithm or tuning policy.
* General configuration-change propagation through {{CacheAccessService}}.
* Migration of {{BucketCache}} to a native {{CacheEngine}} implementation.
* Changes to cache admission, placement, promotion, or eviction policy.
* Making every {{CacheEngine}} dynamically resizable.
* Topology-level selection of the engine that participates in heap-memory 
tuning.

h2. Acceptance Criteria

* {{ResizableCacheEngine}} represents the optional runtime-resizing capability 
for
  {{CacheEngine}} implementations.
* {{LruCacheEngine}} implements {{ResizableCacheEngine}}.
* A native {{LruCacheEngine}} can be resized at runtime through
  {{ResizableCacheEngine.setMaxSize(long)}}.
* Existing {{LruCacheEngine.setMaxSize(long)}} behavior is preserved.
* Cache engines that do not support dynamic resizing are not required to 
implement
  {{setMaxSize()}}.
* Legacy {{ResizableBlockCache}} implementations retain their resizing 
capability when adapted to
  {{CacheEngine}}, where applicable.
* Existing {{HeapMemoryManager}}, {{CombinedBlockCache}}, and legacy 
heap-memory tuning behavior
  remain unchanged.
* Relevant cache-engine and block-cache tests continue to pass.

  was:
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.


> 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
>            Priority: Major
>             Fix For: 4.0.0-alpha-1
>
>
> h2. Description
> The new block cache architecture represents cache implementations through 
> {{CacheEngine}}, but
> {{CacheEngine}} currently has no capability for changing the maximum cache 
> size at runtime.
> Dynamic cache sizing is required by HBase heap-memory tuning. In the legacy 
> cache architecture this
> capability is represented by {{ResizableBlockCache}} and {{setMaxSize(long)}}.
> {{CombinedBlockCache}} also implements {{ResizableBlockCache}} and applies 
> dynamic resizing to its
> first-level cache only. This preserves the expected heap-memory tuning 
> behavior for tiered legacy
> caches.
> The new cache architecture needs an equivalent capability so that native 
> {{CacheEngine}}
> implementations can participate in dynamic cache sizing after RegionServer 
> cache ownership is
> migrated to {{CacheAccessService}}.
> Dynamic resizing should be represented as an optional cache engine 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.
> This issue establishes the cache-engine resizing capability only. Migration of
> {{HeapMemoryManager}} to the new cache architecture requires migration of 
> {{HRegionServer}} cache
> ownership from {{BlockCache}} to {{CacheAccessService}} and is therefore 
> outside the scope of this
> issue.
> h2. Current Architecture
> {{HeapMemoryManager}} is currently created by {{HRegionServer}} using the 
> legacy {{BlockCache}}
> instance.
> Dynamic cache sizing therefore follows the legacy cache hierarchy:
> {noformat}
> HRegionServer
>       |
>       v
>   BlockCache
>       |
>       v
> HeapMemoryManager
>       |
>       v
> ResizableBlockCache
>       |
>       v
>  setMaxSize(...)
> {noformat}
> For {{CombinedBlockCache}}, the resizing operation applies to the first-level 
> cache while the
> second-level cache remains unchanged.
> This behavior should remain unchanged until {{HRegionServer}} and 
> {{HeapMemoryManager}} are migrated
> to the new cache architecture.
> h2. Target Capability
> The new architecture should provide an equivalent optional resizing 
> capability:
> {noformat}
> CacheEngine
>     |
>     v
> ResizableCacheEngine
>     |
>     v
> setMaxSize(...)
> {noformat}
> A cache engine that supports runtime resizing implements 
> {{ResizableCacheEngine}}.
> A cache engine that does not support dynamic resizing does not implement the 
> interface and does not
> need to provide a no-op {{setMaxSize()}} implementation.
> h2. Proposed Changes
> * Introduce {{ResizableCacheEngine}} as an optional {{CacheEngine}} 
> capability.
> * Make {{LruCacheEngine}} implement {{ResizableCacheEngine}}.
> * Preserve the existing {{LruCacheEngine.setMaxSize(long)}} behavior.
> * Preserve dynamic-resizing capability when legacy {{ResizableBlockCache}} 
> implementations are
>   adapted to {{CacheEngine}}, where applicable.
> * Add tests for resizing a native {{LruCacheEngine}} through 
> {{ResizableCacheEngine}}.
> * Add tests for preservation of resizing capability through legacy cache 
> adapters, where
>   applicable.
> h2. Future Integration
> After {{HRegionServer}} cache ownership is migrated from {{BlockCache}} to
> {{CacheAccessService}}, {{HeapMemoryManager}} can be migrated to operate on
> {{ResizableCacheEngine}} instead of {{ResizableBlockCache}}.
> At that point, selection of the cache engine participating in heap-memory 
> tuning should preserve the
> existing semantics:
> * For a single-tier topology, resize the {{SINGLE}} engine when it implements
>   {{ResizableCacheEngine}}.
> * For a tiered topology, resize the heap-resident {{L1}} engine when it 
> implements
>   {{ResizableCacheEngine}}.
> * {{L2}} should not be resized merely because it belongs to the same topology.
> That integration is intentionally deferred to the 
> RegionServer/{{CacheAccessService}} ownership
> migration.
> h2. Out of Scope
> * Changes to {{HRegionServer}} cache ownership.
> * Migration of {{HeapMemoryManager}} from 
> {{BlockCache}}/{{ResizableBlockCache}} to
>   {{CacheAccessService}}/{{ResizableCacheEngine}}.
> * Changes to {{CombinedBlockCache}} resizing behavior.
> * Changes to the {{HeapMemoryTuner}} algorithm or tuning policy.
> * General configuration-change propagation through {{CacheAccessService}}.
> * Migration of {{BucketCache}} to a native {{CacheEngine}} implementation.
> * Changes to cache admission, placement, promotion, or eviction policy.
> * Making every {{CacheEngine}} dynamically resizable.
> * Topology-level selection of the engine that participates in heap-memory 
> tuning.
> h2. Acceptance Criteria
> * {{ResizableCacheEngine}} represents the optional runtime-resizing 
> capability for
>   {{CacheEngine}} implementations.
> * {{LruCacheEngine}} implements {{ResizableCacheEngine}}.
> * A native {{LruCacheEngine}} can be resized at runtime through
>   {{ResizableCacheEngine.setMaxSize(long)}}.
> * Existing {{LruCacheEngine.setMaxSize(long)}} behavior is preserved.
> * Cache engines that do not support dynamic resizing are not required to 
> implement
>   {{setMaxSize()}}.
> * Legacy {{ResizableBlockCache}} implementations retain their resizing 
> capability when adapted to
>   {{CacheEngine}}, where applicable.
> * Existing {{HeapMemoryManager}}, {{CombinedBlockCache}}, and legacy 
> heap-memory tuning behavior
>   remain unchanged.
> * Relevant cache-engine and block-cache tests continue to pass.



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

Reply via email to