HBase核心参数优化

背景

     HBase作为一个使用方便的数据库,除了必要参数外,基本可以做到安装即可使用。但是随着数据量和并发量的增加,默认配置可能没办法很好地支撑数据和业务的处理,轻则效率低下,重则系统不可用,所以在这种情况下,需要进行性能优化,下面就从几个方面来说说HBase的几个核心参数的优化

正文

Region

Region是HBase中的表是根据row key的值水平分割而成的。一个region包含表中所有row key位于region的起始键值和结束键值之间的行,所以Region是HBase中数据存储的载体,该载体包含内存存储以及文件存储。

hbase.hregion.max.filesize 

默认为 10G,简单理解为 Region 中所有文件大小的总和大于该值就会进行 split 。

实际生产环境中该值不建议太大,也不能太小。

太大会导致系统后台执行 compaction 消耗大量系统资源,一定程度上影响业务响应;

太小会导致 Region 分裂比较频繁(分裂本身其实对业务读写会有一定影响),这样的话单个 RegionServer 中必然存在大量 Region,太多 Region 会消耗大量维护资源。

而且每台RegionServer的write cache是有上限的,如果触发上限,会导致HBase "stop the world and flush memstore",这样对整个业务来说是不可接受的,所以Region个数在满足业务的前提下,也要考虑到RegionServer的负载以及该节点上write cache的总大小,以避免触发业务不可用的场景。

此外Region数量过大会在 RegionSever 下线迁移时比较耗时耗资源。

而且在HBase中也有逻辑控制如果单个RegionServer上的Region数量超过1000,则RegionServer会停止Region的split操作。

综合考虑,建议线上设置为 50G 左右。

Memstore

上面说的Region中包含内存存储以及文件存储,而Memstore即是内存存储,也是HBase的writecache。一个Region有一个Memstore,数据写入时首先写入Memstore,Memstore达到一定的阈值后会触发flush操作,生成文件从而做到持久化。

hbase.hregion.memstore.flush.size

默认 128M(134217728),memstore 大于该阈值就会触发 flush。如果当前系统 flush 比较频繁,并且内存资源比较充足,可以适当将该值调整为 256M。调大的副作用可能是造成宕机时需要分裂的 hlog 数量变多,从而延长故障恢复时间。

另外调整该值时需要考虑到该Region所在RegionServer的数量,因为每个memstore的flush size * region的个数的总量比write cache大太多,而每个region写入比较均衡的话,可能会出现每个memstore都还没达到flush的阈值,就已经触发了全局的stop the world and flush memstore,这种情况在生产环境下一定要尽量避免。

hbase.hregion.memstore.block.multiplier

默认值为 4,表示一旦某 region 中所有写入 memstore 的数据大小总和达到或超过阈值 hbase.hregion.memstore.block.multiplier*hbase.hregion.memstore.flush.size,就会执行 flush 操作,并抛出 RegionTooBusyException 异常。

该值在笔者使用的 HBase1.2中的默认值为 4,由于不同版本该值的默认值不同,大家可以检查一下 HBase 版本的配置值,旧的版本默认值为 2。如果日志中出现如下内容:

RegionTooBusyException: Above memstore limit, regionName=xxxxx ...

这个是 Region 的 memstore 占用内存大小超过正常的 4 倍,这时候会抛异常,写入请求会被拒绝,然后开始flush Memstore。

该情况的产生大概率是因为突然插入一个特别大的值,超过了memstore 占用内存大小的 4 倍,或者一批次的写入总量超过了memstore 占用内存大小的 4 倍,此时Memstore进入保护机制,flush掉之后再恢复写入,防止内存被撑爆。

如果上面的情况,优先考虑避免超大值的插入或者控制一批写入的数据量,如果此方案无法实现,就需要考虑修改该参数值了。

hbase.regionserver.global.memstore.size

默认值为 0.4,表示占用总 JVM 内存大小的 40%,该参数非常重要,就是上面频繁提到的“stop the world and flush memstore”的阈值。整个 RegionServer 上所有写入 memstore 的数据大小总和不能超过该阈值,否则会阻塞所有写入请求并强制执行 flush 操作,直至总 memstore 数据大小降到hbase.regionserver.global.memstore.lowerLimit 以下。

在onheap模式下,如果业务特点是写多读少,可以适当增大,如写内存:0.65,读内存:0.15;反之则可以反向调整,但是不管哪种模式,读写内存之和不要超过0.8,否则会有OOME的风险

另外在 offheap 模式下,read cache绝大部分放在堆外(CBC模式下有一小部分在堆内),所以该值可以配置为 0.6~0.65,如果写多读少还可以分配的再多一点。一旦写入出现阻塞,立马查看日志定位,错误信息类似如下:

regionserver.MemStoreFlusher: Blocking updates on hostname,16020,1522286703886: the global memstore size 1.3 G is >= than blocking 1.3 G size

regionserver.MemStoreFlusher: Memstore is above high water mark and block 528ms

一般情况下不会出现这类异常,但如果出现就需要明确以下情况:

  • 该RegionServer上region 数目是不是太多
  • 单表列族设置的太多
  • 该参数设置是否太小

hbase.regionserver.global.memstore.lowerLimit

默认值 0.95,表示 RegionServer 级别总 MemStore 大小的低水位是 hbase.regionserver.global.memstore.size 的 95%。这个参数表示 RegionServer 上所有写入 MemStore 的数据大小总和一旦超过这个阈值,就会挑选最大的 MemStore 执行强制flush操作;而如果flush的速度赶不上写入的速度,很快达到了hbase.regionserver.global.memstore.size的阈值,就会触发“stop the world and flush memorystore”来保护内存不被撑爆

hbase.regionserver.optionalcacheflushinterval

默认值为 3600000(即 1 小时),hbase 会起一个线程定期 flush 所有 memstore,时间间隔就是该值配置。

生产线上如果有实时数据流入HBase,则该值建议设大,比如 12h。因为很多场景下1小时 flush 一次会导致产生很多小文件,一方面导致 flush 比较频繁,一方面导致小文件很多,影响随机读性能。

BlockCache

       上面的Memstore是HBase的write cache,BlockCache就是HBase的read cache,所有的HBase read都从BlockCache开始。不同 BlockCache 策略对应不同的参数,而且这里参数配置会影响到 Memstore 相关参数的配置。笔者对 BlockCache 策略一直持有这样的观点:RegionServer 内存在20G以内的就选择 LRUBlockCache,大于20G的就选择BucketCache 中的 Offheap 模式。接下来所有的相关配置都基于 BucketCache 的 offheap 模型进行说明。

hfile.block.cache.size

默认0.4,该值用来设置LRUBlockCache的内存大小,0.4表示JVM内存的40%。

当前 HBase 系统默认采用 LRUBlockCache 策略,BlockCache 大小和 Memstore 大小均为 JVM 的40%。但对于 BucketCache 策略来讲,Cache 分为了两层(Combine BlockCache,简称CBC),L1 采用LRUBlockCache,主要存储 HFile 中的元数据 Block,L2 采用 BucketCache,主要存储业务数据 Block。因为只用来存储元数据 Block,所以只需要设置很小的 Cache 即可。建议线上设置为 0.05~0.1 左右。

hbase.bucketcache.ioengine

BucketCache 策略的模式选择,可选择 heap、offheap 以及 file 三种,分别表示使用堆内内存、堆外内存以及 SSD 硬盘作为缓存存储介质。

hbase.bucketcache.size

堆外存大小,设置的大小主要依赖物理内存大小。

配置file模式的参数(线上环境针对内存资源不足,某段时间使用 SSD 存储 cache):

# SSD

hbase.bucketcache.ioengine=file:/disk/disk11/hbase_ssd/cache.data

hbase.bucketcache.size=20GB

Compaction

      上文已经介绍,Memstore在达到了flush的阈值后就会flush数据到硬盘。由于一个region属于一个table,一个table有多个列族,则一个region同样有多个列族,而一个列族有一个memestore,​所以一次flush生成列族数个文件。由于数据不断的flush,生成的文件数会越来越多,如果不进行处理,那么磁盘上的小文件会越来越多,影响磁盘的效率同时也影响数据读取效率,在这种背景下就有了compaction 模块。

这个模块的主要用来合并小文件,分为minor compact和major compact。minor compact按照配置进行文件合并,将符合条件的文件合并成一个文件(可能是所有文件,也可能是部分文件),这个过程是条件触发的,下面的参数绝大部分都关于minor compact的;major compact则会将该region中所有文件合并成一个文件,并且在这个过程中删除过期数据、delete 数据等,这个是定时执行的,也可以禁止定时执行,根据情况手动执行。compact涉及参数较多,对于系统读写性能影响也很重要,下面主要介绍部分比较核心的参数。

hbase.hstore.compactionThreshold

默认值为 3,compaction 的触发条件之一,当 store 中文件数超过该阈值就会触发compaction。通常建议生产线上写入较高的系统调高该值,比如 5~10 之间。

如在任意一个 hstore 中有超过此数量的 HStoreFiles,则将运行minor compact以将所有 HStoreFiles 文件作为一个 HStoreFile 重新写入。(每次 memstore 刷新写入一个 HStoreFile)您可通过指定更大数量延长压缩,但minor compact将运行更长时间。在compact期间,更新无法刷新到磁盘。长时间compact需要足够的内存,以在compact的持续时间内记录所有更新。如太大,compact期间客户端会超时。

hbase.hstore.compaction.max

默认值为 10,最多可以参与 minor compaction 的文件数。该值通常设置为 hbase.hstore.compactionThreshold 的 2~3 倍。

hbase.regionserver.thread.compaction.throttle

默认值为 2G,评估单个 compaction 为 small 或者 large 的判断依据。为了防止 large compaction 长时间执行阻塞其他 small compaction,HBase 将这两种 compaction 进行了分离处理,每种 compaction 会分配独立的线程池。

hbase.regionserver.thread.compaction.large/small

默认值为 1,large 和 small compaction 的处理线程数。生产线上建议设置为 5,强烈不建议再调太大(比如10),否则会出现性能下降问题。

在写入负载比较高的集群,可以适当增加这两个参数的值,提高系统 Compaction 的效率。但是这两个参数不能太大,否则有可能出现 Compaction 效率不增反降到现象,要结合生产环境测试。

hbase.hstore.blockingStoreFiles

默认值为10,表示一旦某个 store 中文件数大于该阈值,就会导致所有更新阻塞。生产线上建议设置该值为 100,避免出现阻塞更新,一旦发现日志中出现如下日志信息:

too many store files; delaying flush up to 90000ms

这时就要查看该值是否设置正确了。

hbase.hregion.majorcompaction

默认值为 604800000(即 一周),表示 major compaction 的触发周期。

由于major compaction消耗资源较大,执行时间较长,对HBase性能产生很大的影响,所以生产线上建议大表手动执行 major compaction,需要将此参数设置为0,即关闭自动触发机制,然后通过脚本或者人工来执行此动作。

Request队列相关参数

hbase.regionserver.handler.count

默认值为 30,服务器端用来处理用户请求的线程数。生产线上通常需要将该值调到 100~200。

用户关心的请求响应时间由两部分构成:排队时间和服务时间,即 response time = queue time + service time。优化系统需要经常关注排队时间,如果用户请求排队时间很长,首要关注的问题就是 hbase.regionserver.handler.count 是否没有调整。

hbase.ipc.server.callqueue.handler.factor

默认值为 0,服务器端设置队列个数,默认只有1个队列。假如该值为 0.1,那么服务器就会设置 handler.count*0.1=30*0.1=3 个队列。

hbase.ipc.server.callqueue.read.ratio

默认值为 0,服务器端设置读写业务分别占用的队列百分比以及 handler 百分比。默认所有请求使用所有的队列,先到先得。但是某些场景下需要控制读写分离,就需要设置该值了。假如该值为0.5,表示读写各占一半队列,同时各占一半 handler。

hbase.ipc.server.call.queue.scan.ratio

默认值为 0,即读数据时候所有请求使用所有队列,但某些场景下服务器端为了将 get 和 scan 隔离,需要设置该参数。假如该值为0.5,表示scan和get各占一半读队列,同时各占一半读handler,结合上面的hbase.ipc.server.callqueue.read.ratio的0.5,则各占所有资源的25%。

队列相关参数设置比较复杂,为了方便理解,举例如下:

<property>

<name>hbase.regionserver.handler.count</name>

<value>100</value>

</property>

<!--RegionServer会设置100*0.1=10个队列处理用户的请求-->

<property>

<name>hbase.ipc.server.callqueue.handler.factor</name>

<value>0.1</value>

</property>

<!--10个队列中分配5(10*0.5)个队列处理用户的读请求,另外5个队列处理用户的写请求-->

<property>

<name>hbase.ipc.server.callqueue.read.ratio</name>

<value>0.5</value>

</property>

<!--5个队列中分配1(5*0.2)个队列处理用户的scan请求,另外4个队列处理用户的get请求-->

<property>

<name>hbaes.ipc.server.callqueue.scan.ratio</name>

<value>0.2</value>

</property>

其他重要参数

hbase.online.schema.update.enable

默认值为 true,表示更新表 schema 的时候不再需要先 disable 再 enable,直接在线更新即可。该参数在HBase 2.0之后默认为true。

生产线上建议设置为true。

hbase.quota.enabled

默认值为 false,表示是否开启 quota 功能,quota 的功能主要是限制用户/表的 QPS,起到限流作用。

hbase.snapshot.enabled

默认值为 true,表示是否开启 snapshot 功能,snapshot 功能主要用来备份 HBase 数据。

生产线上建议设置为true。

zookeeper.session.timeout

默认值为 180s,表示 Zookeeper 客户端与服务器端 session 超时时间,超时之后 RegionServer 将会被踢出集群。

有两点需要重点关注:其一是该值需要与 Zookeeper 服务器端 session 相关参数一同设置才会生效。但是如果一味的将该值增大而不修改 Zookeeper 服务端参数,可能并不会实际生效。其二是通常情况下离线集群可以将该值设置较大,在线业务需要根据业务对延迟的容忍度考虑设置。详细介绍可见zookeeper.session.timeout相关参数与配置详解

总结

综上而看,HBase在不同维度不同的场景有着不同的配置方式,所以在一个场景下效率极高的配置在另外一个场景下可能会大大折扣甚至还不如默认配置。这就需要我们的HBase设计和维护人员在HBase使用之前和使用中不断摸索对HBase进行的配置优化,从而达到适合自己业务场景的最佳效果。所以HBase还是有一定的使用门槛的,没有大一统万能的配置。但是如果跨过门槛后能正确使用HBase,HBase也会给用户带来很好的性能表现以及用户体验。

传送门:HBase完整文档:HBase生产环境从入门到熟练使用,这一篇文章就够了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值