HBase配置调优

/ HBase / 70浏览

硬件

标签 说明
节点规划 2个主节点 + 8个工作节点
工作节点内存 64G
工作节点磁盘大小 1T
工作节点CPU核数 8核
主节点内存 32G
主节点磁盘大小 256G
主节点CPU核数 4核

将0.2比例的内存预留给系统内存。在除了系统内存的基础上,再将0.2比例的内存用于HDFS内存和ZooKeeper内存。故规划HBase可用内存 = 64 0.8 0.8 = 41G。

软件配置

独立HBase集群 + HDFS + ZooKeeper

业务读写比例:1 :(10 - 100)

参数配置

Region规划

官方推荐:

​ 单个Region大小在10G - 30G之间。

​ 单台RegionServer的Region,控制在20 - 300之间。

Region过大或者过小所带来的影响:

Region计算

根据Region大小计算Region数

1. 计算单台机器可用磁盘空间

   2. 从Region最小值开始算,Region数量 = HBase可用磁盘空间 / (region_size * hdfs副本数)
   3. 如果得到的Region数 > 200,则增大region_size,重新计算Region数。依次类推。region_size 范围在 10G ~ 30G之间。

根据Region数计算Region大小。(具有Region数量经验值)

1. 计算单台机器可用磁盘空间

   2. RegionSize = HBase可用磁盘空间 / (Region数 * HDFS副本数)

由Region大小可以推算:

1T / (10G * 3) = 33。每个RegionServer中,Region数量为33个。

Region大小在官方推荐范围,单RegionServer中Region数量也在官方推荐范围。故:Region大小设置为10G,较为合理。

因此,Region参数设置:hbase.hregion.max.filesize:10G

内存规划

RegionServer中,BlockCache有两种:

对于超小内存,8G以下

直接使用LRUBlockCache。

使用堆外内存的主要目的是避免GC时间过久,对HBase稳定性带来影响。由于总内存很小,即使将读写缓存在堆内存中,GC时长也不会太高。

对于超大内存,128G以上

使用BucketCache。

完全作为堆内存,GC时对线上读写会造成延迟。

常规内存:8G ~ 128G

写多读少时:写缓存利用率高,使用LRUBlockCache尽量提高堆内写缓存的使用率。(写数据时,是缓存在堆内的。)

写少读多时:读缓存利用率高,使用BucketCache尽量提高堆外读缓存的使用率。

使用堆外内存的主要原因是,保证读请求的稳定。

为了保证线上HBase稳定性,缓存建议选择堆外缓存。

hbase.bucketcache.ioengine=offheap

内存占用比例

理论上,最优的配置是:硬盘维度下的Region个数 等于 JavaHeap维度下的Region个数

变量 说明 配置项
DiskSize 硬盘空间大小,我们是1T
RegionSize 单个Region的大小,根据前面,我们推荐配置:10G hbase.hregion.max.filesize
ReplicationFactor HDFS副本数。我们默认配置3个副本 dfs.replication
HeapFractionForMemstore JavaHeap写缓存大小,即RegionServer内存中,MemStore总大小。该配置是一个比例 hbase.regionserver.global.memstore.lowerLimit
MemstoreSize Memstore刷写大小 hbase.hregion.memstore.flush.size

已知:

DiskSize / (RegionSize * ReplicationFactor) = JavaHeap * HeapFractionForMemstore / (MemstoreSize / 2 )

HBase默认:

RegionSize: 10G
ReplicationFactor: 3

MemstoreSize: 128M
HeapFractionForMemstore: 0.4

求:

DiskSize / JavaHeap

得出:磁盘和内存比例大小为:192 :1

目前64G内存,HBase可用内存41G。需要:41 * 192 = 7872G磁盘。我们实际只有1T磁盘。

为了最优,解决方案:

  1. 增加硬盘
  2. 调整内存参数

写缓存参数

内存布局:

在这里插入图片描述

写缓存:MemStore的Flush,分别为:MemStore刷写、Region刷写、RegionServer刷写。

其中,RegionServer的刷写会阻塞所有请求,直至刷写完成。对线上影响最大,需要尽量避免频繁的刷写RegionServer。

虽然Memstore和Region影响不会很大,但是控制其中的刷写频率可以进一步提升性能。

由于目前我们的内存 > 硬盘。因此,可以适当的提高Memstore内存大小。故:

Memstore大小设置为:256M,默认值128M。

在RegionServer总内存中,JavaHeap尽量不应太高,过高会导致GC时长大。JavaHeap建议给16G内存。

得到几个配置:

hbase.hregion.memstore.flush.size=256M

JavaHeap堆栈大小:16G

HeapFractionForMemstore:0.26

1024 / 10 3 = 16 x / 0.125

hbase.regionserver.global.memstore.upperLimit=0.36

整个RegionServer中,memstore最大比例

hbase.regionserver.global.memstore.lowerLimit=0.26

整个RegionServer中,memstore最小比例

故,写缓存大小为:4.16G。

读缓存参数

根据上面信息:

读缓存一般由:堆内元数据 和 堆外数据缓存 组成。两部分的内存占比一般:1:9(网上参考经验值)

故:元数据内存大小给:25/9=2.78G。约为3G。

因此得到以下配置:

hbase.bucketcache.size=(25 + 3)* 1024M:

读缓存大小,单位为M

hbase.bucketcache.percentage.in.combinedcache=0.9

堆外读缓存占比,剩余为堆内元数据缓存大小

hfile.block.cache.size=0.3

blockcache 和 memstore,它们的大小之和必须小于java_heap_size* 0.8。

16 * 0.8 > blockcache + 4.16 blockcache < 8.64。8.48 / 28 > 0.3

总结

RegionServer JavaHeap堆栈大小: 16G
hbase.hregion.max.filesize=10G
hbase.bucketcache.ioengine=offheap
hbase.hregion.memstore.flush.size=256M
hbase.hregion.memstore.block.multiplier=2
hbase.regionserver.global.memstore.upperLimit=0.36
hbase.regionserver.global.memstore.lowerLimit=0.26
hbase.bucketcache.size=28 * 1024M
hbase.bucketcache.percentage.in.combinedcache=0.9
hfile.block.cache.size=0.3

其他

HBase服务端

高并发情况下,如果HBase服务端处理线程数不够,应用层将会收到HBase服务端抛出的无法创建新线程的异常从而导致应用层线程阻塞。

可以释放调整HBase服务端配置以提升处理性能:

#  Master处理客户端请求最大线程数   
hbase.master.handler.count=256
# RS处理客户端请求最大线程数,如果该值设置过大则会占用过多的内存,导致频繁的GC,或者出现OutOfMemory
hbase.regionserver.handler.count=256
# 客户端缓存大小,默认为2M  
hbase.client.write.buffer=8M
# scan缓存一次获取数据的条数,太大也会产生OOM
hbase.client.scanner.caching=100

另外,以下两项中,默认设置下超时太久、重试次数太多,一旦应用层连接不上HBse服务端将会进行近乎无限的重试,长连接无法释放,新请求不断进来,从而导致线程堆积应用假死等,影响比较严重,可以适当减少:

hbase.client.retries.number=3   
hbase.rpc.timeout=10000

HDFS

适当增加处理线程等设置:

dfs.datanode.handler.count=64
dfs.datanode.max.transfer.threads=12288
dfs.namenode.handler.count=256
dfs.namenode.service.handler.count=256

同时,对于HDFS的存储设置也可以做以下优化:

# 可以配置多个,拥有多个元数据备份
dfs.name.dir
# 配置多个磁盘与路径,提高并行读写能力
dfs.data.dir
# dn同时处理文件的上限,默认为256,可以提高到8192
dfs.datanode.max.xcievers