标签:property pool 额外 分配 reduce values 除了 控制 ssd
Block Cache
HBase提供了两种不同的BlockCache实现,用于缓存从HDFS读出的数据。这两种分别为:
下面我们会讨论每种方法的优点和缺点、如何对两种方式做选择,以及这两种类型的相关配置。
Cache Choices
LruBlockCache是最初始的实现,并且全部存在Java堆内存中。BucketCache是另一个选择,主要用于将block cache的数据存在off-heap(堆外内存),不过BlockCache也可以作为一种文件备份式的缓存。
当开启了BucketCache后,便启用了两级缓存的系统。以前我们会用“L1”和“L2”来描述这两个等级,但是现在这个术语已经在hbase-2.0.0后被弃用了。现在“L1” cache 直接指的是LruBlockCache,“L2”指的是一个off-heap的BucketCache。(hbase-2.0.02之后)当BucketCache启用后,所有数据块(DATA block)会被存在BucketCache 层,而meta 数据块(INDEX 以及BLOOM块)被存在on-heap的LruBlockCache中。管理这两层缓存,以及指示数据块如何在它们之间移动的策略,由CombinedBlockCache完成。
Cache的常规配置
除了缓存它自己的实现以外,我们也可以设置一些常规的配置选项,用于控制cache的行为。具体可以参考CacheConfig的文档:
https://hbase.apache.org/devapidocs/org/apache/hadoop/hbase/io/hfile/CacheConfig.html
在设置或修改了任何属性后,需要重启HBase集群以让配置文件生效。若是遇到异常,可以进一步查看HBase中的报错。
LruBlockCache的设计
LruBlockCache是一个LRU缓存,包括三种优先级,以适应于于:scan-resistance 以及 in-memory ColumnFamilies场景。三种优先级分别为:
若是想了解更具体的信息,可以参考LruBlockCache 源码
LruBlockCache 的使用
一般来说,BlockCache在所有用户表中默认是开启的,也就是说,任何的读操作均会加载LRU Cache。这个方案可能适用于大部分场景,但是,如果需要达到更优的performance,仍需要做一些调整。其中一个很重要的概念是working set size(或WSS),它的意思是:为了解决一个问题所需要的资源(内存)大小。对于一个网站来说,这个便是在短时间内响应请求所需要的数据量。计算在HBase中到底有多少内存可供cache的方法为:
number of region servers * heap size * hfile.block.cache.size * 0.99
block.cache的默认值是0.4,表示可用堆内存的40%。最后一个值(99%)是:在缓存内存收回开始后,默认可被回收的比率(这里若是值是100%,则不太现实,因为在置换时也会有新块写入?)。下面是使用这个公式的一些例子:
当然,被存在block cache中的并不仅仅只是你的数据,下面是其他一些需要被考虑到的地方:
当前来说,衡量HFile索引以及Bloom filter 大小的一种推荐的方法是:查看region server UI,并查看相关指标。对于键来说,获取抽样时,可以使用HFile的命令行工具,并查看键的平均大小。从HBase 0.98.3以后,可以在UI界面中的Block Cache部分,查看BlockCache的详细状态以及指标。
一般来说,如果当前可用内存并不足以支持WSS,则不建议使用block caching。举个例子:假设在集群中一共有40GB的可用内存分布于各个region server的block cache,但是你需要处理1TB的数据,则这种场景不太适合使用block caching。其中一个原因是:回收(置换)缓存会打乱内存分布,并触发更多本没必要的垃圾回收。下面是两个场景:
仅缓存META数据块(DATA 数据块在fscache)
一个有趣的设置是:仅缓存 META数据块,每次在读取数据时,均去访问DATA数据块。在这种情况下如果DATA数据块适应于fscache,且当访问数据的操作在一个很大的集群中完全是随机时,这种设置是可取的。若要开启这个设置,可以直接修改表:对某个列族,设置BLOCKCACHE => ‘false’。这样就关闭了对这个列族的BlockCache。不过,META数据块的block caching无法被关闭,即使它的被关闭了,META数据块也仍会被载入缓存。
堆外(Off-heap)Block Cache
如何开启BucketCache
一个通常的部署BucketCache方式是通过一个管理类,它设置两级缓存:一个堆内的缓存,由LruBlockCache实现;以及第二层缓存,由BucketCache实现。默认管理的类为CombinedBlockCache。简单的说,这个类实现的缓存规则是:将meta数据块(INDEX以及BLOOM)放在堆内缓存(LruBlockCache层),而将DATA数据放入BucketCache层。
在HBase-2.00 版本之前
在hbase 2.00 版本以前,从BucketCache取数据时都会比较慢(对比使用堆内存的LruBlockCache)。然而,从表现来看,读操作的延迟时间基本趋于稳定。因为在使用BucketCache时,会有较少的垃圾回收(BucketCache管理BlockCache的分配,而不是GC)。如果BucketCache被部署为堆外(off-heap)模式,则这部分内存根本不会被GC管理。这就是为什么你在2.0.0版本之前的HBase使用BucketCache时,延迟时间基本趋于稳定,并可以减轻GC以及堆内存碎片的影响,这样可以安全的使用更多内存。如果你希望缓存不被GC管理,可以使用BucketCache。
在2.0.0版本前,在配置了BucketCache后,可以减少LruBlockCache置换的影响。所有数据以及index块首先被缓存在L1。当L1中发生缓存清除(置换)时,被置换出的数据块会被移动到L2。在Java中,可以通过HColumnDescriptor.setCacheDataInL1(true)设置cacheDataInL1;在hbase shell中可以设置CACHE_DATA_IN_L1 为true,例如:create ‘t1’, {NamE => ‘t1’, CONFIGURATION => {CACHE_DATA_IN_L1 => ‘true’}}
HBase-2.0.0 版本之后
HBASE-11425改变了HBase的数据读取路径,实现了直接从堆外读取数据。off-heap的延迟可以接近于on-heap的延迟,因为off-heap并不会引起GC操作。
从HBase 2.0.0 开始,L1与L2的概念便被弃用。当BucketCache启用时,数据块(DATA blocks)会一直保存于BucketCache;INDEX/BLOOM块会保存于LRUBlockCache的堆内存。cacheDetaInL1 的配置也被移除。
BucketCache的块缓存可以被部署为off-heap,文件,或mmaped文件这三种模式(通过hbase.bucketcache.ioengine配置)。设置为offheap会让BucketCache在堆外内存管理block cache。设置为file:PATH_TO_FILE(EMR里默认为files:/mnt/hbase/bucketcache),会直接让BucketCache使用文件缓存(如果卷是SSD之类的高速盘的话,会比较有用)。从2.0.0 开始,使用多个文件路径也是可以的。若是在需要较大Cache 的场景下,这个配置很有用。在设置时的基本配置为:files:PATH_TO_FILE1, PATH_TO_FILE2, PATH_TO_FILE3。BucketCache可以也可以配置为使用一个mmapped文件。配置ioengine为mmap:PATH_TO_FILE即可。
在hbase 2.0.0之前,也可以设置多级缓存(绕过CombinedBlockCache策略),将BucketCache设置为严格的L2 缓存,LruBlockCache为L1缓存。在这种配置中,设置 hbase.bucketcache.combinedcache.enable 为false即可。在这种模式下,当L1缓存内容被清除(置换)时,会将置换出的块放入L2。当一个块被缓存时,首先被缓存在L1。当我们去查询一个缓存块时,首先在L1查,若是没找到,则再搜索L2。我们将此部署方法称为Raw L1+L2。需要注意的是,这个L1+L2模式已经在hbase 2.0.0 以后被移除了。当BucketCache被使用时,它会严格的将DATA块缓存放入BucketCache,而INDEX/META块则被放入LruBlockCache。
其他BucketCache的配置包括:指定cache被持久化的路径以在重启后仍存在、写cache的线程数量,等等。在检查它是否开启时,可以查看日志内容,会包含cache的设置;它会详细的记录BucketCache被部署的信息。也可以通过UI,它可以看到详细的cache层级以及它们的配置。
BucketCache示例配置
这个例子提供了为一个4GB堆外BucketCache、1GB堆内缓存的配置。配置过程在RegionServer上实施。
设置hbase.bucketcache.ioengine,并设置 hbase.bucketcache.size > 0,开启CombinedBlockCache。这里我们假设当前RegionServer配置了5GB的堆内存(HBASE_HEAPSIZE=5g)
<property>
<name>hbase.bucketcache.ioengine</name>
<value>offheap</value>
</property>
<property>
<name>hfile.block.cache.size</name>
<value>0.2</value>
</property>
<property>
<name>hbase.bucketcache.size</name>
<value>4196</value>
</property>
上面的配置文件中,我们设置了BucketCache为4G,配置on-heap LruBlockCache为20%的RegionServer的堆内存(0.2 × 5G = 1G)。
HBASE-10641以后,HBase 0.98及以后的版本,引入了可以为BucketCache配置多个bucket以及它们的大小的功能。配置多个bucket sieze,可以设置hbase.bucketcache.bucket.sizes为一系列块大小设置,从小到大。它的目的是根据你数据访问模式,优化bucket sizes。下面是一个示例配置,大小从4096到8192:
<property>
<name>hbase.bucketcache.bucket.sizes</name>
<value>4096,8192</value>
</property>
Direct Memory Usage in HBase
默认最大可以使用的direct memory因JVM的不同而不同。传统下是64M,或者通过直接分配堆内存(-Xmx),或完全没有限制(如JDK7)。HBase服务器使用direct memory,特别是short-circuit reading(读数据不经过DataNode,客户端直接读文件),RegionServer上的DFSclient会分配direct memory buffers。DFSClient会使用的内存大小并不容易量化;它是由:打开的HFile文件数量 × hbase.dfs.client.read.shortcircuit.buffer.size 决定。hbase.dfs.client.read.shortcircuit.buffer.size在HBase中设置为128k(参考hbae-default.xml默认配置)。如果需要使用off-heap block caching,则需要使用到直接内存(direct memory)。在RPC Server中,也会使用一个ByteBuffer池,从hbase 2.0.0开始,这些缓冲区为off-heap ByteBuffers。在启动JVM时,确保 -XX:MaxDirectMemorySize 的设置(在hbase-env.sh)考虑到了off-heap BlockCache(hbase.bucketcache.size)、DFSClient的使用量,以及RPC端的ByteBufferPool的最大总和大小。Direct memory 的大小应该比 off-heap BlockCache + max ByteBufferPool 的大小更大。在一般情况下,可以在基于所需的direct memory大小情况下,额外再分配多1-2GB的空间。Direct memory属于Java进程堆的一部分,与对象堆(由-Xmx分配)分离。MaxDirectMemorySize的大小必须小于物理的RAM大小,并且小于所有可用的RAM大小(由于内存的其他用处,以及系统的限制)。
你可以在UI中的Server Metrics: Memory 栏看到一个RegionServer配置的内存量(on-heap以及off-heap/direct memory)。这部分数据也可以通过JMX获取。
BlockCache 压缩
HBASE-11331引入了lazy BlockCache decompression。在开启此功能后,DATA(以及ENCODED_DATA)数据块会以它们on-disk的形式缓存到BlockCache。与默认的模式不同点在于:默认情况下,在缓存一个数据块时,会先解压缩、解密,然后存入缓存(因为数据块是从HDFS取)。而lazy BlockCache decompression 直接将数据块存入缓存。
如果一个RegionServer存储的数据过多,无法适当的将大部分数据放入缓存,则开启这个功能(使用SNAPPY压缩)后,实验证明:可以提升50%的throughput,30%的平均延迟上升,增加80%垃圾回收,以及2%的整体CPU负载。
对于一个RegionServer,如果它的数据量已经适合cache的大小,或者你的应用对额外的CPU或GC的负载格外敏感,则这个选项不会有太大用处。
默认情况下,这个功能是关闭的,若要开启,可以在所有的RegionServer中的hbase-site.xml文件里设置 hbase.block.data.cachecompressed 为 true
References:
http://hbase.apache.org/book.html#arch.overview
标签:property pool 额外 分配 reduce values 除了 控制 ssd
原文地址:https://www.cnblogs.com/zackstang/p/10061379.html