本文介绍LruBlockCache如何获取缓存数据。
缓存数据的获取是在方法getBlock()中实现的,代码如下:
/**
* Get the buffer of the block with the specified name.
* @param cacheKey block's cache key
* @param caching true if the caller caches blocks on cache misses
* @param repeat Whether this is a repeat lookup for the same block
* (used to avoid double counting cache misses when doing double-check locking)
* @param updateCacheMetrics Whether to update cache metrics or not
* @return buffer of specified cache key, or null if not in cache
*/
@Override
public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,
boolean updateCacheMetrics) {
LruCachedBlock cb = map.get(cacheKey);
if (cb == null) {
if (!repeat && updateCacheMetrics) stats.miss(caching, cacheKey.isPrimary());
// If there is another block cache then try and read there.
// However if this is a retry ( second time in double checked locking )
// And it's already a miss then the l2 will also be a miss.
if (victimHandler != null && !repeat) {
Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);
// Promote this to L1.
if (result != null && caching) {
cacheBlock(cacheKey, result, /* inMemory = */ false, /* cacheData = */ true);
}
return result;
}
return null;
}
if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary());
cb.access(count.incrementAndGet());
return cb.getBuffer();
}
实现逻辑如下:
1、首先,从LruBlockCache的map中直接获取;
2、如果map中没有,则在victimHandler存在且!repeat的情况下,通过victimHandler的getBlock()方法获取并缓存到LruBlockCache中,即综合考虑第二种缓存模式,并同步到第一种缓存中;
3、如果1或2能够获取到数据,更新统计数据,且通过缓存块的access方法,更新访问时间accessTime,将可能的BlockPriority.SINGLE升级为BlockPriority.MULTI;
4、返回。