产生的原因:前段时间由于设置region server 的heapsize 为16g,使得block cache 的大小变为16g*0.4=3.2g,查看日志发现了jvm 隔一段时间会出现如下日志:
2015-03-24 16:09:27,405 WARN org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 15959ms
GC pool 'ParNew' had collection(s): count=1 time=213ms
GC pool 'ConcurrentMarkSweep' had collection(s): count=1 time=16158ms
--
2015-03-24 16:28:42,048 WARN org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 20125ms
GC pool 'ParNew' had collection(s): count=1 time=337ms
GC pool 'ConcurrentMarkSweep' had collection(s): count=2 time=20206ms
由此可以断定block cache 发生了CMS GC,长达10s,甚至20s,
目前使用的BlockCache,使用一个HashMap维护Block Key到Block的映射,采用严格的LRU算法来淘汰Block,初始化时会指定容量大小,当使用量达到85%的时候开始淘汰block至75%的比例。
优点:直接采用jvm提供的HashMap来管理Cache,简单可依赖;内存用多少占多少,JVM会帮你回收淘汰的BlOCK占用的内存
缺点:
1.一个Block从被缓存至被淘汰,基本就伴随着Heap中的位置从New区晋升到Old区
2.晋升在Old区的Block被淘汰后,最终由CMS进行垃圾回收,随之带来的是Heap碎片 ,old 区域变大导致cms 时间过长。
3.因为碎片问题,随之而来的是GC时晋升失败的FullGC,我们的线上系统根据不同的业务特点,因为这个而发生FullGC的频率,有1天的,1周的,1月半年的都有。对于高频率的, 在运维上可以通过在半夜手工触发FullGC来缓解
4.如果缓存的速度比淘汰的速度快,很不幸,现在的代码有OOM的风险(这个可以修改下代码避免)
解决方案:
hbase-0.94以后提供了BucketCache, 一方面降低region server heap size 的大小为8gb,降低cms发生的几率和减少时间,另一方面可以利用BucketCache增加二级缓存。二级缓可以利用off heap cache,也可也利用ssd 做二级缓存。
CDH5.3.0 的配置如下:在region server 上添加
XX:MaxDirectMemorySize=16G
在region server hbase-site 配置BucketCache size:
<property>
<name>hbase.bucketcache.ioengine</name>
<value>offheap</value>
</property>
<property>
<name>hbase.bucketcache.percentage.in.combinedcache</name>
<value>0.8</value>
</property>
<property>
<name>hbase.bucketcache.size</name>
<value>16384</value>
</property>
由于增加了读缓存:已缓存的块增加了一倍,总的命中率增加了60%多
参考文档:
http://www.slideshare.net/bijugs/h-base-performance
http://zh.hortonworks.com/blog/hbase-blockcache-101/
http://zjushch.iteye.com/blog/1751387
http://blog.csdn.net/bluishglc/article/details/21516067
http://punishzhou.iteye.com/blog/1277141