HBase提供了两种不同的BlockCache实现来缓存从HDFS读取的数据:默认的堆上LruBlockCache和BucketCache(通常是堆外)。 本节讨论每种实现的优缺点,如何选择适当的选项以及每种实现的配置选项。
LruBlockCache是原始实现,并且完全在Java堆中。 虽然BucketCache也可以是文件支持的缓存,但BucketCache是可选的,并且主要用于保持块缓存数据不在堆中。 在文件支持下,我们既可以在文件模式下使用它,也可以在mmaped模式下使用它。 我们还有pmem模式,其中存储桶缓存位于永久性存储设备上。
启用BucketCache时,将启用两层缓存系统。 我们以前将层描述为“ L1”和“ L2”,但是从hbase-2.0.0开始不赞成使用此术语。 “ L1”缓存引用LruBlockCache的实例,“ L2”引用堆外的BucketCache。 相反,启用BucketCache时,所有DATA块都保留在BucketCache层中,而元块(INDEX和BLOOM块)在LruBlockCache中处于堆中状态。 这两个层的管理以及指示块之间如何移动的策略是由CombinedBlockCache完成的。
常规缓存配置
除了缓存实现本身之外,您还可以设置一些常规配置选项来控制缓存的执行方式。 请参阅CacheConfig。 设置这些选项中的任何一个之后,请重新启动或滚动重新启动群集,以使配置生效。 检查日志中是否有错误或意外行为。
LruBlockCache设计
LruBlockCache是一个LRU高速缓存,其中包含三个级别的块优先级,以允许进行扫描抵抗和内存中的ColumnFamilies:
单一访问优先级:首次从HDFS加载块时,它通常具有此优先级,它将成为驱逐期间要考虑的第一个组的一部分。优点是,与使用率更高的块相比,扫描的块更有可能被驱逐。
多路访问优先级:如果再次访问先前优先级组中的块,则会升级到该优先级。因此,它是驱逐期间考虑的第二组的一部分。
内存中访问优先级:如果该块的系列被配置为“内存中”,则无论其访问次数如何,它都是该优先级的一部分。目录表的配置如下。该小组是驱逐期间考虑的最后一个小组。
要将列族标记为内存中,请调用
HColumnDescriptor.setInMemory(true);
如果使用Java创建表,或者在外壳中创建或更改表时将IN_MEMORY⇒设置为true:
hbase(main):003:0> create 't', {NAME => 'f', IN_MEMORY => 'true'}
LruBlockCache的用法
默认情况下,所有用户表都启用块缓存,这意味着任何读取操作都将加载LRU缓存。这对于许多用例而言可能是好的,但是通常需要进行进一步的调整才能获得更好的性能。一个重要的概念是工作集大小或WSS,即:“计算问题答案所需的内存量”。对于网站而言,这就是在短时间内回答查询所需的数据。
计算HBase中可用于缓存的内存量的方法是:
区域服务器数量堆大小 hfile.block.cache.size * 0.99
块高速缓存的默认值为0.4,它表示可用堆的40%。最后一个值(99%)是LRU缓存中默认的可接受的加载因子,在此之后开始逐出。之所以将其包含在此等式中,是因为说有可能使用100%的可用内存是不切实际的,因为这会使进程从加载新块的位置开始阻塞。这里有些例子:
一台将堆大小设置为1 GB并且默认块高速缓存大小的区域服务器将具有405 MB的块高速缓存可用。
20个区域服务器(堆大小设置为8 GB)和默认块高速缓存大小将具有63.3的块高速缓存。
100个区域服务器(堆大小设置为24 GB,块缓存大小为0.5)将具有约1.16 TB的块缓存。
您的数据不是块缓存的唯一居民。以下是您可能需要考虑的其他事项: