@InterfaceAudience.Private public class LruBlockCache extends Object implements FirstLevelBlockCache
HeapSize,
 memory-bound using an LRU eviction algorithm, and concurrent: backed by a
 ConcurrentHashMap and with a non-blocking eviction thread giving
 constant-time cacheBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey, org.apache.hadoop.hbase.io.hfile.Cacheable, boolean) and getBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey, boolean, boolean, boolean) operations.
 Contains three levels of block priority to allow for scan-resistance and in-memory families
 HColumnDescriptor.setInMemory(boolean) (An in-memory column
 family is a column family that should be served from memory if possible):
 single-access, multiple-accesses, and in-memory priority.
 A block is added with an in-memory priority flag if
 HColumnDescriptor.isInMemory(), otherwise a block becomes a
 single access priority the first time it is read into this block cache.  If a block is
 accessed again while in cache, it is marked as a multiple access priority block.  This
 delineation of blocks is used to prevent scans from thrashing the cache adding a
 least-frequently-used element to the eviction algorithm.
Each priority is given its own chunk of the total cache to ensure fairness during eviction. Each priority will retain close to its maximum size, however, if any priority is not using its entire chunk the others are able to grow beyond their chunk size.
Instantiated at a minimum with the total size and average block size. All sizes are in bytes. The block size is not especially important as this cache is fully dynamic in its sizing of blocks. It is only used for pre-allocating data structures and in initial heap estimation of the map.
 The detailed constructor defines the sizes for the three priorities (they
 should total to the maximum size defined).  It also sets the levels that
 trigger and control the eviction thread.
 The acceptable size is the cache size level which triggers the eviction
 process to start.  It evicts enough blocks to get the size below the
 minimum size specified.
Eviction happens in a separate thread and involves a single full-scan of the map. It determines how many bytes must be freed to reach the minimum size, and then while scanning determines the fewest least-recently-used blocks necessary from each of the three priorities (would be 3 times bytes to free). It then uses the priority chunk sizes to evict fairly according to the relative sizes and usage.
| Modifier and Type | Class and Description | 
|---|---|
| private class  | LruBlockCache.BlockBucketUsed to group blocks into priority buckets. | 
| (package private) static class  | LruBlockCache.EvictionThread | 
| (package private) static class  | LruBlockCache.StatisticsThread | 
| Modifier and Type | Field and Description | 
|---|---|
| private float | acceptableFactorAcceptable size of cache (no evictions if size < acceptable) | 
| private long | blockSizeApproximate block size | 
| static long | CACHE_FIXED_OVERHEAD | 
| private AtomicLong | countCache access count (sequential ID) | 
| private LongAdder | dataBlockElementsCurrent number of cached data block elements | 
| private LongAdder | dataBlockSizeCurrent size of data blocks | 
| (package private) static float | DEFAULT_ACCEPTABLE_FACTOR | 
| (package private) static int | DEFAULT_CONCURRENCY_LEVEL | 
| private static float | DEFAULT_HARD_CAPACITY_LIMIT_FACTOR | 
| private static boolean | DEFAULT_IN_MEMORY_FORCE_MODE | 
| (package private) static float | DEFAULT_LOAD_FACTOR | 
| private static long | DEFAULT_MAX_BLOCK_SIZE | 
| private static float | DEFAULT_MEMORY_FACTOR | 
| private static float | DEFAULT_MIN_FACTOR | 
| private static float | DEFAULT_MULTI_FACTOR | 
| private static float | DEFAULT_SINGLE_FACTOR | 
| private AtomicLong | elementsCurrent number of cached elements | 
| private boolean | evictionInProgressVolatile boolean to track if we are in an eviction process or not | 
| private ReentrantLock | evictionLockEviction lock (locked when eviction in process) | 
| private LruBlockCache.EvictionThread | evictionThreadEviction thread | 
| private boolean | forceInMemoryWhether in-memory hfile's data block has higher priority when evicting | 
| private float | hardCapacityLimitFactorhard capacity limit | 
| private static org.slf4j.Logger | LOG | 
| private static String | LRU_ACCEPTABLE_FACTOR_CONFIG_NAMEAcceptable size of cache (no evictions if size < acceptable) | 
| (package private) static String | LRU_HARD_CAPACITY_LIMIT_FACTOR_CONFIG_NAMEHard capacity limit of cache, will reject any put if size > this * acceptable | 
| private static String | LRU_IN_MEMORY_FORCE_MODE_CONFIG_NAMEConfiguration key to force data-block always (except in-memory are too much)
 cached in memory for in-memory hfile, unlike inMemory, which is a column-family
 configuration, inMemoryForceMode is a cluster-wide configuration | 
| private static String | LRU_MAX_BLOCK_SIZE | 
| private static String | LRU_MEMORY_PERCENTAGE_CONFIG_NAME | 
| private static String | LRU_MIN_FACTOR_CONFIG_NAMEPercentage of total size that eviction will evict until; e.g. | 
| private static String | LRU_MULTI_PERCENTAGE_CONFIG_NAME | 
| private static String | LRU_SINGLE_PERCENTAGE_CONFIG_NAME | 
| private ConcurrentHashMap<BlockCacheKey,LruCachedBlock> | mapDefined the cache map as  ConcurrentHashMaphere, because ingetBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey, boolean, boolean, boolean), we need to guarantee the atomicity of map#computeIfPresent
 (key, func). | 
| private long | maxBlockSize | 
| private long | maxSizeMaximum allowable size of cache (block put if size > max, evict) | 
| private float | memoryFactorIn-memory bucket size | 
| private float | minFactorMinimum threshold of cache (when evicting, evict until size < min) | 
| private float | multiFactorMultiple access bucket size | 
| private long | overheadOverhead of the structure itself | 
| private ScheduledExecutorService | scheduleThreadPoolStatistics thread schedule pool (for heavy debugging, could remove) | 
| private float | singleFactorSingle access bucket size | 
| private AtomicLong | sizeCurrent size of cache | 
| private static int | STAT_THREAD_PERIOD | 
| private CacheStats | statsCache statistics | 
| private BlockCache | victimHandlerWhere to send victims (blocks evicted/missing from the cache). | 
| Constructor and Description | 
|---|
| LruBlockCache(long maxSize,
             long blockSize)Default constructor. | 
| LruBlockCache(long maxSize,
             long blockSize,
             boolean evictionThread)Constructor used for testing. | 
| LruBlockCache(long maxSize,
             long blockSize,
             boolean evictionThread,
             org.apache.hadoop.conf.Configuration conf) | 
| LruBlockCache(long maxSize,
             long blockSize,
             boolean evictionThread,
             int mapInitialSize,
             float mapLoadFactor,
             int mapConcurrencyLevel,
             float minFactor,
             float acceptableFactor,
             float singleFactor,
             float multiFactor,
             float memoryFactor,
             float hardLimitFactor,
             boolean forceInMemory,
             long maxBlockSize)Configurable constructor. | 
| LruBlockCache(long maxSize,
             long blockSize,
             org.apache.hadoop.conf.Configuration conf) | 
| Modifier and Type | Method and Description | 
|---|---|
| (package private) long | acceptableSize() | 
| private Cacheable | asReferencedHeapBlock(Cacheable buf)The block cached in LRUBlockCache will always be an heap block: on the one side, the heap
 access will be more faster then off-heap, the small index block or meta block cached in
 CombinedBlockCache will benefit a lot. | 
| private static void | assertCounterSanity(long mapSize,
                   long counterVal)Sanity-checking for parity between actual block cache content and metrics. | 
| void | cacheBlock(BlockCacheKey cacheKey,
          Cacheable buf)Cache the block with the specified name and buffer. | 
| void | cacheBlock(BlockCacheKey cacheKey,
          Cacheable buf,
          boolean inMemory)Cache the block with the specified name and buffer. | 
| private static long | calculateOverhead(long maxSize,
                 long blockSize,
                 int concurrency) | 
| void | clearCache()Clears the cache. | 
| boolean | containsBlock(BlockCacheKey cacheKey)Whether the cache contains block with specified cacheKey | 
| (package private) void | evict()Eviction method. | 
| boolean | evictBlock(BlockCacheKey cacheKey)Evict block from cache. | 
| protected long | evictBlock(LruCachedBlock block,
          boolean evictedByEvictionProcess)Evict the block, and it will be cached by the victim handler if exists &&
 block may be read again later | 
| int | evictBlocksByHfileName(String hfileName)Evicts all blocks for a specific HFile. | 
| Cacheable | getBlock(BlockCacheKey cacheKey,
        boolean caching,
        boolean repeat,
        boolean updateCacheMetrics)Get the buffer of the block with the specified name. | 
| BlockCache[] | getBlockCaches() | 
| long | getBlockCount()Returns the number of blocks currently cached in the block cache. | 
| (package private) SortedSet<String> | getCachedFileNamesForTest()Used in testing. | 
| long | getCurrentDataSize()Returns the occupied size of data blocks, in bytes. | 
| long | getCurrentSize()Returns the occupied size of the block cache, in bytes. | 
| long | getDataBlockCount()Returns the number of data blocks currently cached in the block cache. | 
| Map<DataBlockEncoding,Integer> | getEncodingCountsForTest() | 
| (package private) LruBlockCache.EvictionThread | getEvictionThread() | 
| long | getFreeSize()Returns the free size of the block cache, in bytes. | 
| (package private) Map<BlockCacheKey,LruCachedBlock> | getMapForTests() | 
| long | getMaxSize()Get the maximum size of this cache. | 
| (package private) long | getOverhead() | 
| CacheStats | getStats()Get counter statistics for this cache. | 
| long | heapSize() | 
| (package private) boolean | isEvictionInProgress() | 
| Iterator<CachedBlock> | iterator() | 
| void | logStats() | 
| private long | memorySize() | 
| private long | minSize() | 
| private long | multiSize() | 
| private void | runEviction()Multi-threaded call to run the eviction process. | 
| void | setMaxSize(long maxSize)Sets the max heap size that can be used by the BlockCache. | 
| void | setVictimCache(BlockCache victimCache)Specifies the secondary cache. | 
| void | shutdown()Shutdown the cache. | 
| private long | singleSize() | 
| long | size()Returns the total size of the block cache, in bytes. | 
| String | toString() | 
| private long | updateSizeMetrics(LruCachedBlock cb,
                 boolean evict)Helper function that updates the local size counter and also updates any
 per-cf or per-blocktype metrics it can discern from given
  LruCachedBlock | 
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitforEach, spliteratorprivate static final org.slf4j.Logger LOG
private static final String LRU_MIN_FACTOR_CONFIG_NAME
private static final String LRU_ACCEPTABLE_FACTOR_CONFIG_NAME
static final String LRU_HARD_CAPACITY_LIMIT_FACTOR_CONFIG_NAME
private static final String LRU_SINGLE_PERCENTAGE_CONFIG_NAME
private static final String LRU_MULTI_PERCENTAGE_CONFIG_NAME
private static final String LRU_MEMORY_PERCENTAGE_CONFIG_NAME
private static final String LRU_IN_MEMORY_FORCE_MODE_CONFIG_NAME
static final float DEFAULT_LOAD_FACTOR
static final int DEFAULT_CONCURRENCY_LEVEL
private static final float DEFAULT_MIN_FACTOR
static final float DEFAULT_ACCEPTABLE_FACTOR
private static final float DEFAULT_SINGLE_FACTOR
private static final float DEFAULT_MULTI_FACTOR
private static final float DEFAULT_MEMORY_FACTOR
private static final float DEFAULT_HARD_CAPACITY_LIMIT_FACTOR
private static final boolean DEFAULT_IN_MEMORY_FORCE_MODE
private static final int STAT_THREAD_PERIOD
private static final String LRU_MAX_BLOCK_SIZE
private static final long DEFAULT_MAX_BLOCK_SIZE
private final transient ConcurrentHashMap<BlockCacheKey,LruCachedBlock> map
ConcurrentHashMap here, because in
 getBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey, boolean, boolean, boolean), we need to guarantee the atomicity of map#computeIfPresent
 (key, func). Besides, the func method must execute exactly once only when the key is present
 and under the lock context, otherwise the reference count will be messed up. Notice that the
 ConcurrentSkipListMap can not guarantee that.private final transient ReentrantLock evictionLock
private final long maxBlockSize
private volatile boolean evictionInProgress
private final transient LruBlockCache.EvictionThread evictionThread
private final transient ScheduledExecutorService scheduleThreadPool
private final AtomicLong size
private final LongAdder dataBlockSize
private final AtomicLong elements
private final LongAdder dataBlockElements
private final AtomicLong count
private float hardCapacityLimitFactor
private final CacheStats stats
private long maxSize
private long blockSize
private float acceptableFactor
private float minFactor
private float singleFactor
private float multiFactor
private float memoryFactor
private long overhead
private boolean forceInMemory
private transient BlockCache victimHandler
public static final long CACHE_FIXED_OVERHEAD
public LruBlockCache(long maxSize, long blockSize)
All other factors will be calculated based on defaults specified in this class.
maxSize - maximum size of cache, in bytesblockSize - approximate size of each block, in bytespublic LruBlockCache(long maxSize, long blockSize, boolean evictionThread)
public LruBlockCache(long maxSize, long blockSize, boolean evictionThread, org.apache.hadoop.conf.Configuration conf)
public LruBlockCache(long maxSize, long blockSize, org.apache.hadoop.conf.Configuration conf)
public LruBlockCache(long maxSize, long blockSize, boolean evictionThread, int mapInitialSize, float mapLoadFactor, int mapConcurrencyLevel, float minFactor, float acceptableFactor, float singleFactor, float multiFactor, float memoryFactor, float hardLimitFactor, boolean forceInMemory, long maxBlockSize)
maxSize - maximum size of this cache, in bytesblockSize - expected average size of blocks, in bytesevictionThread - whether to run evictions in a bg thread or notmapInitialSize - initial size of backing ConcurrentHashMapmapLoadFactor - initial load factor of backing ConcurrentHashMapmapConcurrencyLevel - initial concurrency factor for backing CHMminFactor - percentage of total size that eviction will evict untilacceptableFactor - percentage of total size that triggers evictionsingleFactor - percentage of total size for single-access blocksmultiFactor - percentage of total size for multiple-access blocksmemoryFactor - percentage of total size for in-memory blockspublic void setVictimCache(BlockCache victimCache)
FirstLevelBlockCachesetVictimCache in interface FirstLevelBlockCachevictimCache - the second level cachepublic void setMaxSize(long maxSize)
ResizableBlockCachesetMaxSize in interface ResizableBlockCachemaxSize - The max heap size.private Cacheable asReferencedHeapBlock(Cacheable buf)
buf - the original blockpublic void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory)
It is assumed this will NOT be called on an already cached block. In rare cases (HBASE-8547) this can happen, for which we compare the buffer contents.
cacheBlock in interface BlockCachecacheKey - block's cache keybuf - block bufferinMemory - if block is in-memoryprivate static void assertCounterSanity(long mapSize, long counterVal)
public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf)
TODO after HBASE-22005, we may cache an block which allocated from off-heap, but our LRU cache sizing is based on heap size, so we should handle this in HBASE-22127. It will introduce an switch whether make the LRU on-heap or not, if so we may need copy the memory to on-heap, otherwise the caching size is based on off-heap.
cacheBlock in interface BlockCachecacheKey - block's cache keybuf - block bufferprivate long updateSizeMetrics(LruCachedBlock cb, boolean evict)
LruCachedBlockpublic Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat, boolean updateCacheMetrics)
getBlock in interface BlockCachecacheKey - block's cache keycaching - true if the caller caches blocks on cache missesrepeat - Whether this is a repeat lookup for the same block
                           (used to avoid double counting cache misses when doing double-check
                           locking)updateCacheMetrics - Whether to update cache metrics or notpublic boolean containsBlock(BlockCacheKey cacheKey)
containsBlock in interface FirstLevelBlockCachecacheKey - cache key for the blockpublic boolean evictBlock(BlockCacheKey cacheKey)
BlockCacheevictBlock in interface BlockCachecacheKey - Block to evictpublic int evictBlocksByHfileName(String hfileName)
This is used for evict-on-close to remove all blocks of a specific HFile.
evictBlocksByHfileName in interface BlockCacheprotected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess)
evictedByEvictionProcess - true if the given block is evicted by
          EvictionThreadprivate void runEviction()
boolean isEvictionInProgress()
long getOverhead()
void evict()
public long getMaxSize()
getMaxSize in interface BlockCachepublic long getCurrentSize()
BlockCachegetCurrentSize in interface BlockCachepublic long getCurrentDataSize()
BlockCachegetCurrentDataSize in interface BlockCachepublic long getFreeSize()
BlockCachegetFreeSize in interface BlockCachepublic long size()
BlockCachesize in interface BlockCachepublic long getBlockCount()
BlockCachegetBlockCount in interface BlockCachepublic long getDataBlockCount()
BlockCachegetDataBlockCount in interface BlockCacheLruBlockCache.EvictionThread getEvictionThread()
public void logStats()
public CacheStats getStats()
Includes: total accesses, hits, misses, evicted blocks, and runs of the eviction processes.
getStats in interface BlockCachepublic long heapSize()
private static long calculateOverhead(long maxSize, long blockSize, int concurrency)
public Iterator<CachedBlock> iterator()
iterator in interface Iterable<CachedBlock>iterator in interface BlockCachelong acceptableSize()
private long minSize()
private long singleSize()
private long multiSize()
private long memorySize()
public void shutdown()
BlockCacheshutdown in interface BlockCachepublic void clearCache()
SortedSet<String> getCachedFileNamesForTest()
public Map<DataBlockEncoding,Integer> getEncodingCountsForTest()
Map<BlockCacheKey,LruCachedBlock> getMapForTests()
public BlockCache[] getBlockCaches()
getBlockCaches in interface BlockCacheCopyright © 2007–2021 The Apache Software Foundation. All rights reserved.