BlockCache的优化

一.简单介绍

1.在以前学习Hbase的时候,对BlockCache几乎是没有听说过,不过它也是比较重要的hbase的一部分,有些在生产环境中的性能问题,都是靠优化BlockCache来解决的。

2.首先我们要知道一个RegionServer只有一个BlockCache。我们根据其单词名称可以判断是以恶搞块缓存,而往往缓存都是和内存有关,有了这些,接下来就好懂了。

3.BlockCache知识用于优化读取性能的,可以设置不开启,默认是开启的。
可以使用下面的shell命令进行关闭

 alter 'table1',CONFIGURATION=>{NAME=>'cf',BLOCKCACHE=>'false'}

接下来介绍几种BlockCache的实现方案

二.BlockCache的实现方案

2.1.LRUBlock Cache

LRU的意思是Leaset Recently Used 即最近最少使用,我们在学习操作系统学过的LRU,FIFO一样。读出的block会放到BlockCache 中待下次查询使用。如果缓存满了会根据LRU淘汰算法进行淘汰相关的block。
LRUBlockCache分为三个部分:

在这里插入图片描述
这个方案是仿照Java的JVM而设计的

in-memory:这个属性并不是说这个列族就会存放到列族中,而是和其他的列族一样会存放到硬盘上。一般的列族经过第一次被访问会存放到singke-access中,多次访问会存放到multi-access中。

对于in-memory=true的列族,会被存放到in-memeory,并且在in-memory区域里的列族的block拥有最长存活时间,当需要删除block的,这个区域的列族是最后考虑的
仅仅只是为了BlockCache而创造的。

和MemStore的联动关系
当我们设置hfile.block.cache.size的时候需要主要memStore的影响
MemStore+BlockCache的总内存不能够超过80%,巧合的是,二者默认的最大内值都是0.4,所以如果你需要改动其中一个的话,另外一个也需要改动。一般情况下不需要改动

LRUBlock Cache的坏处?
随着于内存对象的增多,如果引发Full GC 那么就可怕了,将会导致整个JVM成语停止状态,有时候会有几分钟的停滞,这也是Spark core的劣势之一,感兴趣的话,可以了解一下Spark。

2.2.SlabCache
2.2.1.SlabCache的说明

对于LRUBlockCache引发GC,那么我们就使用这个方案就可以解决,怎样解决呢?还是使用堆内存吗?当然不可能了,既然不适用堆内存,那么只能使用堆外内存来拜托GC的限制了。

可以使用-XX:MaxDirectMe morySize=10MB进行设置

尽管可以使JVM不会被停顿,但是它带来的坏处更多:
(1).堆外内存就相当于一片无人管理的荒野,存储都是原始的数据,如果是个对象必须序列化后才能存储,因此不能存储复杂的对象
(2).和JVM没啥关系,所有内存泄漏,排查起来比较困难
(3).使用系统内存,如果使用量过于大的话,有可能物理内存会爆掉,也有可能会影响硬盘使用

2.2.2.SlabCache的实现

SlabCache被划分为两个区域,区域大小是按照堆外内存的80%,20%进行划分,并且调用了nio的DirectByteBuffer进行实现的
两个区域分别
(1)存放大小约等于1个BlockSize(64KB)默认值的Block。
(2)存放大小约等于2个BlockSize默认值的Block。

如果你存放的Block的大小大于BlockSize的1倍到2倍之间,那么将不会被存储,那么将会使用LRU对这些没有存储的对象进行淘汰

BlockSize的值可以通过修改列族的BLOCKSIZE,如果你修改了BLOCKSIZE的属性,这两个区域都不会被用到,SlabCache将会和LRU一起使用

当一个Block被取出的时候同时被放到SlabCache和LRUCache中。
当读请求到来的时候先查看LRUCache,如果查不到就去查
SlabCache,如果查到了就把Block放到LRUCache中。

感觉SlabCache 是二级缓存,并且在生产环境中,这个方案对GC的改善并不是很大,用得不是很多

2.3. Bucket Cache
2.3.1.介绍

和SlabCache一样,Bucket Cache也是使用堆外内存。
和SlabCache类似,不过也改进了许多

  • 区域并不是两个了,而是初始化的是十四个区域Block大小分别为4KB、8KB、16KB、32KB、40KB、48KB、56KB、64KB、96KB、128KB、192KB、256KB 384KB、512KB,并且区域数量以及Block大小都是可以改变的
    可以通过hbase.bucketcache.bucket.sizes进行配置,配置多个使用逗号进行分割

  • BucketCache并不一定会采用堆外内存的方式,而是有三种选择,堆(heap) 堆外(offheap) 以及文件(file) 可以通过hbase.bucketcache.ioengine设置,默认是offheap

  • 每个Block的大小上限是最大尺寸的block*4
    比如可以容纳的最大的Block类型是512KB,那么每个Bucket的大小就是512KB *
    4 = 2048KB

  • 系统一启动BucketCache就会把可用的存储空间按照每个Bucket
    的大小上限均分为多个Bucket。如果划分完的数量比你的种类还
    少,比如比14(默认的种类数量)少,就会直接报错,因为每一
    种类型的Bucket至少要有一个Bucket

2.3.2.好处:
  • BucketCache还有一个特别的长处,那就是它自己来划分内存空
    间、自己来管理内存空间,Block放进去的时候是考虑到offset偏移量
    的(具体可以看源码的BucketAllocator),所以内存碎片少,发生GC
    的时间很短。

  • 之前说的file,其实就是SSD,这个也是这个策略的亮点之一

  • 这种策略极大地改进了SlabCache使用率低的问题。

  • 配置极其灵活,可以适用于多种场景。
    在实际生产环境中,性能也是很不错
    如果你想要某个列族不使用此策略
    可以使用命令:意思是只缓存在LRU中

 base(main):004:0>  alter 'user',CONFIGURATION=>{CACHE_DATA_IN_L1=>'true'}
Updating all regions with the new schema...
1/1 regions updated.
Done.
2.3.2.配置参数:
  • hbase.bucketcache.combinedcache.enabled:是否打开组合模
    式(CombinedBlockCache),默认为true

  • hbase.bucketcache.ioengine:使用的存储介质,可选值为
    heap、offheap、file。不设置的话,默认为offheap

  • hbase.bucketcache.size:BucketCache所占的大小
    如果设置为0.0~1.0,则代表了占堆内存的百分比。
    如果是大于1的值,则代表实际的BucketCache的大小,单位为MB。
    默认值为0.0,即关闭BucketCache
    这个是因为BucketCache既可以用于堆内存,还可以用于堆外内存和硬盘,但是并不推荐一参二用

  • hbase.bucketcache.bucket.sizes:定义所有Block种类,默认为14种,种类之间用逗号分隔。单位为B,每一种类型必须是1024的整数倍,否则会报异常java.io.IOException: Invalid HFile block magic。
    默认值为:4、8、16、32、40、48、56、
    64、96、128、192、256、384、512。

  • -XX:MaxDirectMemorySize:这个参数不是在hbase-site.xml中
    配置的,而是JVM启动的参数。如果你不配置这个参数,JVM会按
    需索取堆外内存;如果你配置了这个参数,你可以定义JVM可以
    获得的堆外内存上限。显而易见的,这个参数值必须比
    hbase.bucketcache.size大。

3.组合模式

之前说了两种方案,但是请记住,无论是SlabCache还是比SaltCache更好一些的BucketCache,都是无法和默认的LRUCache媲美的,尽管它存在GC的问题

用SlabCache时候,一般情况下,是要个LRU组合使用的,LRU为一级缓存,SlabCache为二级缓存

用BucketCache的时候也是一样,不会只会单独使用它,但是和SlabCache不一样,而是使用组合模式(CombinedBlockCahce)

就是说会根据Block的类型来决定存放的位置。比如Index Block和Bloom Block会被放到LRUCache中。Data Block被直接放到BucketCache中,

所以数据会去LRUCache查询一下,然后再去BucketCache中查询真正的数据。
其实这种实现是一种更合理的二级缓存,数据一级缓存到二级缓存最后到硬盘,数据是从小到大,存储介质也是由快到慢。考虑到成本和性能的组合,比较合理的介质是:LRUCache使用内存->BuckectCache使用SSD->HFile使用机械硬盘。

LRUCache和BucketCache的比较:

  • 为BucketCache自己控制内存空间,碎片比较少,所以GC时间大部分时间都比LRUCache短
  • 在缓存全部命中的情况下,LRUCache的吞吐量是BucketCache的两倍;在缓存基本命中的情况下,LRUCache的吞吐量跟BucketCache基本相等。
  • 读写延迟,IO方面两者基本相等。
  • 缓存全部命中的情况下,LRUCache比使用fiile模式的BucketCache CPU占用率低一倍,但是跟其他情况下差不多

因此从整体情况来看,默认的LRUCache合适要好于Buckcache的,只不过如果存在Full GC时候也可以使用BucketCache适当调节一下

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值