Skip to content

HBase 内存调优

内存调优主要目的是:合理规划memstore的内存分配,提高写入性能。

注意以下几点:

  1. 应当开启CMS的内存压缩功能,防止memstore算盘后堆区出现内存碎片。过多内存碎片可能导致新生代升级失败,触发GC;
  2. memstore的刷盘阈值,要和region数目匹配。原则上:(RegionServer内存 * 分配给MemStore比例) > (Memstore 大小 * 列簇数量),当然有一到二倍的超配问题也不大。
  3. 使用bulk load时,需要注意hbase.hregion.memstore.block.multiplier配置。该配置指:单个Memstore的大小超过指定倍数(2倍)时 ,region会阻止新的写入并且触发flush。 一旦region被锁住,regionserver隔一段时间再检查memstore是不是低于阀值。这会导致hbase.server.thread.wakefrequency(10s)之内无法再写入。
  4. 避免 hbase.hstore.blockingStoreFiles 到达上限,导致region。block

MemStore 触发 flush 的场景

  1. 单个memstore的内存达到,hbase.hregion.memstore.flush.size 触发写盘。但是此时不会锁住region。
  2. 单个memstore的内存达到,hbase.hregion.memstore.flush.size * hbase.hregion.memstore.block.multiplier。触发flush,并且锁住该region。hbase.hregion.memstore.flush.size这个配需要考虑RS中Region数目,在压力测试中,由于Client一直在写入,该参数太大非常容易照成memstore内存到达高水位线,导致整个RS block,
  3. memstore的总内存达到 hbase.regionserver.global.memstore.lowerLimit (0.35),此时最大memstore发生flush。
  4. memstore的总内存达到 hbase.regionserver.global.memstore.upperLimit (0.4), 此时所有RS发生flush,此时整个RS阻塞。
  5. WAL大小达到上限,hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs(2GB),这个值应该大于lowerLimit的值,flush不应该由这个条件触发

建议:

hbase.hregion.memstore.flush.size * Region num = hbase.regionserver.global.memstore.upperLimit * RS JVM Mem 根据上面的公式,除了Region Num数目以外,其他参数在生产中都是固定的。平时定位HBase性能问题时,我们可以通过判断当前RS中的Region数目来判断,HBase需不需要扩容。

HBase的查询性能

通过 hfile.block.cache.size(0.2) 配置直接影响数据读的性能。通常情况下,upperLimit和该配置的和,应该小于0.8,否则容易OOM。

频繁触发MemStore 同样会影响读性能

  1. 频繁flush,产生大量的HFile。这样HBase在检索的时候,就不得不读取大量的HFile,读性能会受很大影响。

  2. 过多的合并会产生额外的负载。

  3. 当Compaction处理是跟集群上的其他请求并行进行的,当HBase不能及时完成Compaction的时候(同样有阈值设置项),会在RS上出现“写阻塞”。

MSLAB

MSLAB可以避免HBase发生长时间的Full GC,但是这样可能导致内存利用率下降,已经性能的下降,通过G1+MSLAB,几乎可以完全杜绝Full GC。

hbase.hregion.memstore.mslab.enabled:设置为true,即打开MSLAB,默认是true。
hbase.hregion.memstore.chunkpool.maxsize:表示在整个Memstore可以占用的堆内存的比例。默认值是0,因此设置大于0,才算真正开启MSLAB.
hregion.memstore.chunkpool.initialsize:表示在RegionServer启动的时候预分配一些chunk出来。也是一个比例值,该值表示预分配的chunk占用总的chunkpool的大小。
hbase.hregion.memstore.mslab.chunksize:每一个chunk的大小,默认是2048*1024,即2MB。
hbase.hregion.memstore.mslab.max.allocation:能放入chunk的最大单元格大小,默认是256KB,已经很大了。

参考:https://juejin.im/post/5c024eedf265da611e4d64f4

压缩算法

当CPU性能足够时,开启压缩能够提升读写能力。原因是:CPU计算使用的时间,通常小于IO时间。

HStore

HStore对应了table中的一个CF列族,包含:MemStore和StoreFile(底层实现是HFile)。当其中一个CF的Memstore达到阈值flush时,会创建一个新的StoreFile。

StoreFile以HFile格式保存在HDFS上,HFile是Hadoop的二进制格式文件。实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile。

PS: 某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终导致系统产生更多的I/O???是这样的吗?

参数名 默认值 说明
hbase.hregion.majorcompaction 默认为7天 配置major合并的间隔时间,默认为1天,可设置为0,禁止自动的major合并,可手动或者通过脚本定期进行major合并。major合并之后,一个store只有一个storeFile文件,会对store的所有数据进行重写,有较大的性能消耗。
hbase.hstore.compactionThreshold/hbase.hstore.compaction.min 3 hstore大于三个的时候,开始minor 合并

Region 数目的控制

手动执行拆分

如何执行预拆分

如何手动负载均衡

如何合并region

性能测试

PE工具