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)