hbase优化之旅(一)探索regionserver参数优化

优化的目的

我们线上hbase集群使用了group分组功能,但没有针对不同业务分组的特点做特殊优化,hbase服务能力没有彻底激发出来。

本文记录了对某个业务分组参数优化的探索,借此机会深入了解不同配置对regionserver监控指标和机器负载的影响。 优化后,单台regionserver查询延迟更低,磁盘IO降低,系统更稳定。从而提高吞吐能力,进而减少机器,提升资源利用率的能力,节约成本。

要解决那些问题

目前该业务分组发现的问题主要在写入。虽然资源利用率不高,但时不时会rpcp99变慢。从监控可以看到,队列等待时间会间隔性变长。看regionserver日志,hlogs上限触发同时刷太多region,flush和compact压力集中。刷了好多小文件,写放大效果明显。

问题分析

分组有17台regionserver,单台有大概520个region,白天请求量较为平稳。分析一台的使用情况。

物理资源使用情况

机器类型

2*E5-2650v4(2*12核),8*32G,2*150G(120G) SATA SSD+12*800G(960G) SATA SSD

机器负载

cpu和load并不高。



内存看,由于应用内存分配较为保守,regionserver堆内堆外共150g,datanode 4g,很大一块给了操作系统读cache。但regionserver本身也配置了100g的读cache,操作系统读cache没什么用。



磁盘读流量较高,写流量50MB/s。网络In 20MB,Out 40到80MB波动。


磁盘读流量主要是本地regionserver 业务读和compact读,写流量主要是本地regionserver写wal,flush,compact,以及其他datanode的写副本。

网络in主要是业务写入请求和其他datanode写副本请求,网络out主要是业务查询响应和regionserver 写wal,flush,compact写其他datanode副本的请求。

由于业务查询主要走内存缓存(95%),hifile又有很高的压缩比(1:5),如果不考虑服务端数据过滤的情况,业务读引起的磁盘IO应该只是网络查询响应IO的百分之一。

当然服务端数据过滤的影响是需要考虑的,但相比网络out磁盘读流量太高了不正常。compact 读小文件写大文件压缩率提高了,这也是磁盘读流量大于网络OUT的可能。 磁盘读流量很大应该是compact读引起的,这个时间段又没有major compacted,说明可能小文件很多引起了写放大。


regionserver使用情况

regionserver配置

版本0.98.21,配置见附录一。

指标监控

队列等待时间p99最多有150ms,执行时间p99(ProcessCallTime_99th_percentile)在45ms内。

读缓存命中率95%,还ok

有一些慢写入


大概20分钟memstore整体刷一次,slowput的出现在刷memstore时


compaction排队的频率和memstore刷新基本一致,无major,说明是memstore定期大flush引起。


flush排队也发生在定期memstore flush时


看regionserver日志,固定间隔就会hlogs上限触发同时刷很多region,22MB的memstore刷5MB hifile,同时刷了好多小文件,又马上compact,写放大效果明显。


09:34:04,075 INFO  [regionserver60020.logRoller] wal.FSHLog: Too many hlogs: logs=53, maxlogs=52; forcing flush of 69 regions(s) ...

09:34:27,339 INFO  [regionserver60020.logRoller] wal.FSHLog: Too many hlogs: logs=53, maxlogs=52; forcing flush of 222 regions(s) ...

...

09:34:27,601 INFO  [MemStoreFlusher.1] regionserver.DefaultStoreFlusher: Flushed, sequenceid=311232252, memsize=22.6 M, hasBloomFilter=true, into tmp file ...

09:34:27,608 INFO  [MemStoreFlusher.1] regionserver.HStore: Added ...., entries=27282, sequenceid=311232252, filesize=5.4 M

09:34:27,608 INFO  [MemStoreFlusher.1] regionserver.HRegion: Finished memstore flush of ~23.6 M/24788698, currentsize=0/0 for region .... in 267ms, sequenceid=311232252, compaction requested=true



堆内存和gc情况,波动主要发生在周期刷memstore时。

问题总结

1.hbase.regionserver.maxlogs太少,

按照hlog和memstore的关系公式


 hbase.regionserver.hlog.blocksize * hbase.reionserver.logroll.mutiplier*hbase.regionserver.maxlogs 
 >= hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE


至少应该是95。配置太低频繁由于hlog上限触发几百个region flush,flush的都是小文件,flush和compact压力都大。

2.内存空闲太多,预留20%空闲就可以了。但要注意g1内存过大可能导致gc时间变长。

3.region数太多,大部分region的memstore没有128MB就强制flush了。正常应尽量保证每个 region 能够分配到 Flushsize 大小的内存,尽可能的 flush 大文件,从而减少后续 Compaction 开销。region数可以通过region合并减少,但这次先不优化,通过增大内存方式缓解。


参数优化探索

第一次修改

期望优化hlogs触发强刷memstore。

hbase.regionserver.maxlogs 52改为95.

重启regionserver。


变成47分钟触发hlog上限刷一次memstore了。

日志看,47分钟左右hlogs上限触发257 region同时刷新。和之前强刷一样,很多memstore20MB,压缩后的hfile5MB。总memstore峰值最多18.35GB,部分region 128MB提前flush了,所以到不了理论上限22.5GB。

compaction排队的频率降低了

队列等待时间波峰的间隔变长,有所改善。


gc次数和时间平常值略有降低,波峰提高。


slowput略有减少。

优化有一定效果。

第二次修改

由于region数太多,单个region可能不到128MB就触发hlog的强刷了。调大内存从而增加memstore和hlogs上限。计算预计在hlog上限前肯定能触发每小时一刷。调大了handler线程数。

hbase-env.sh


1.jvm XX:MaxDirectMemorySize 调为110GB

2.堆内Xmx调为80g


hbase-site.xml


3.hbase.bucketcache.size 112640  110g,hfile.block.cache.size   0.14 

4.hbase.regionserver.global.memstore.upperLimit   0.56   44.8g,

 hbase.regionserver.global.memstore.lowerLimit  0.5  40g,

5.hbase.regionserver.hlog.blocksize  268435456   256MB,显示配置,默认和hdfs块大小一致,也是配置的这个值。

hbase.regionserver.maxlogs 177

6.hbase.regionserver.handler.count 384


重启regionserver,观察监控。


memstore1小时一降,并不是hlog上限触发的,是每小时定时刷新触发的。


看日志,16:31陆续有region128MB flush。16:59 memstore 17.5GB, hlogs 125时,大部分region触发1小时刷新,delay几秒到几十秒。刷新时间还是较为集中,有flush和compact排队。其中6点的compactsize大且持续,应该是很多region需要compact的hfile变大了。


慢put变多,rpc执行时间峰值变高了,队列等待时间p99最长居然到2s!


原因是gc峰值变高了,影响regionserver业务了。


堆内存变大了,gc回收的变多,gc时间就变长了。

优化有些副作用,要消除。



第三次修改

期望优化增大堆内存引起的gc问题。memstore刷新间隔改为2小时,刷新size改为256MB


1.XX:InitiatingHeapOccupancyPercent=65 调整为XX:InitiatingHeapOccupancyPercent=75  之前hmaxlogs52限制实际memstore最大12g左右,堆内读写缓存加起来0.45左右。现在读写缓存加起来最多0.7了,所以调大触发gc的上限(bad modify)

2. -XX:ConcGCThreads=8,-XX:ParallelGCThreads=30,-XX:G1MixedGCCountTarget=32  增大gc并发,文档说建议逻辑核的5/8,48核30。并发标记跟着调大。拆解gc次数降低单次时间。

3.hbase.regionserver.optionalcacheflushinterval 改  7200000

4.hbase.hregion.memstore.flush.size  268435456  128MB的压缩会也就22MB hfile没多大,所以单个memstore内存改为256MB。  


重启观察。


发现由于同时调大间隔时间和flush size,又变成1小时40分钟hlog上限触发强刷了


看日志,同时刷的region数少了,170个,flush和compact排队有所改善。


rpc和队列时间p99峰值还是太高,慢put不少


整体gc count减少,gc时间峰值变多变高

看gc的日志,调整gc并发,gc的系统时间依然很长,需要继续调整。

第四五次修改

gc触发阈值降低,提前gc。gc并发改小,一次最大10%的region。间隔时间改回1小时。改了两次,最终修改如下

1.XX:InitiatingHeapOccupancyPercent=65, 又改到60  提前 

2. -XX:ConcGCThreads=4,-XX:ParallelGCThreads=16,-XX:G1OldCSetRegionThresholdPercent=10  提高一次gc最多回收的region数。

3. hbase.regionserver.optionalcacheflushinterval 去掉,改回一小时。



重启观察。

memstore又是1小时一刷很多region,由于启动时间较短只执行了几个周期,还没有分散开。


flush和compact排队还是按小时出现


慢put少了,rpc和队列等待p99降低了,但希望能更低一些。


gc变多了,而时间少了一些但峰值依然挺高,看gc日志young gc时间也有挺长的,mixed gc时间依然挺长。

需要继续调优。

第六次修改

继续调gc参数,young gc内存控制大小。继续增大memstore配置让其能2小时一刷。由于region数太多,去掉flush 256MB设置。

-XX:G1MixedGCCountTarget=16    增大一次全局标记后mixed gc最多执行的次数
-XX:G1HeapWastePercent=10   允许保留10%垃圾
-XX:G1MaxNewSizePercent=20   young 上限20%,避免young区太大gc慢
hbase.regionserver.global.memstore.upperLimit 0.6    调大上限
hbase.regionserver.global.memstore.lowerLimit  0.54   
hbase.regionserver.maxlogs 200   调大上限
hbase.regionserver.optionalcacheflushinterval  7200000   2小时一刷
hbase.hregion.memstore.flush.size 去掉用默认128MB


regionserver指标

2小时一刷memstore


flush和compact排队都少了


慢put减少,rpc和队列等待时间p99整体降低,峰值也降了很多

gc更平衡,峰值时间更短


机器负载

cpu load依然很低


磁盘读IO下降到1/4,网络out有所下降。


内存还有20%+的空闲,还可以多用点。

优化有效果。

总结

优化成果

本次优化通过调整regionserver参数和gc参数,减少小文件flush,降低compact写放大。平均响应时间降低,响应时间高峰次数减少。磁盘读写IO减少很多,从而增加了磁盘的使用时间。

后续优化方向

减少region数

单台regionserver上的region偏多。

region都是预分区,预分区时按预估总数据大小计算的分区数,但没考虑hfile压缩。几张大表单region的存储量都是region hfile上限容量的几分之一,可以合并region,减少region数。

增大内存配置

保留10%空闲即可

gc深入调优

这次gc参数调优没有明确目标,没有优化方法论,双盲优化,事倍功半,要深入gc参数细节,用明确的方法论,朝明确的目标优化。敬请期待。

减少服务器

瓶颈可能在存储容量上。hdfs逻辑存储共36.0 T,17台regionserver可以支持50TB逻辑存储容量,可以迭代减少几台,达到节约成本的目的。

附录

hbase-site.xml原始配置

hbase-env.sh原始配置

export HBASE_REGIONSERVER_OPTS="-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps
 -Xloggc:${HBASE_LOG_DIR}/gc-`date +'%Y%m%d%H%M'` -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10
 -XX:GCLogFileSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${HBASE_LOG_DIR}/hbase.heapdump -XX:ErrorFile=${HBASE_LOG_DIR}/hs_err_pid%p.log
 -XX:+PrintAdaptiveSizePolicy -XX:+PrintFlagsFinal -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+UnlockExperimentalVMOptions 
 -XX:+ParallelRefProcEnabled -XX:ConcGCThreads=4 -XX:ParallelGCThreads=16 -XX:G1NewSizePercent=5 
-XX:G1MaxNewSizePercent=60 -XX:MaxTenuringThreshold=1 -XX:G1HeapRegionSize=32m  -XX:G1MixedGCCountTarget=8 -XX:InitiatingHeapOccupancyPercent=65
 -XX:MaxDirectMemorySize=100g -XX:G1OldCSetRegionThresholdPercent=5 -Xmx50g -Xms50g"


g1参考资料

oracle.com/technetwork/

编辑于 2019-02-28

文章被以下专栏收录