一个HBaseCompaction引起的GC问题及其恢复
概况:
生产环境上的一个应用查询功能突然变得十分缓慢,一开始只是偶然出现,后来直接无法使用了,经过排查发现调用HBase的Get接口,响应会超时,这个时候开始去排查HBase服务端的问题。经过排查RegionServer的日志,发现存在3个节点,有严重的GC问题,通过HMaster UI看到这3个RS的Compaction进度无法完成,怀疑这是一次Compaction引起的GC问题,该HBase版本为HBase-2.1.1。
问题现象:
1. 有3个的RS在启动后,执行shortCompaction开始后,内存就持续增长,并且日志中存在JVM Pause,发现都是同个表的3个不同region在做Compaction,而且Compaction中的文件主要是Reference文件
2. HMaster UI上,有3个RS的compaction进度无法完成
3. 使用jmap –dump查看有异常的RS,获取到文件,使用MAT进行分析,发现了占用内存的线程就是shortCompactions
问题恢复:
根据上面前2个信息就基本确定是Compaction引起的内存问题,后面的堆栈是为了进一步定位。已经确定了是Compaction的问题,那么可以针对性的进行恢复。
1. 首先进行紧急恢复手段:临时恢复查询,由于用户的查询业务急需先恢复且该表的写入业务暂停,所以先采取关闭停止这个表的Compaction让RS不再消耗内存。进入hbase shell,修改表的属性,使Compact功能关闭,然后重启异常的3个RS。
alter '表名',METADATA=>{'COMPACTION_ENABLED'=>false} |
2. 首先发现该RS的堆内存设置的过小,根据之前维护的同事说,该集群RS之前一直是2GB的堆内存,出问题后才调整为8GB,从上面MAT显示消耗的内存来看,一个ShortCompaction就已经占用了1.5GB,原来的2GB堆内存显然是不够用的,而当前调整后的的堆内存依然无法完成Compaction,从Master UI上看到,RS重启后,Compaction的进度一开始也是挺快的,到达70%多的时候便变得异常的慢。
3. 恢复手段:
a) 为了不影响当前有查询业务的表,我们对这个表做了一个clone,利用clone_snapshot的方式,将这个表完整的复制成了一个新的表,此时新表它的HDFS文件还是引用的原始表。
b) 因为之前发现Compaction基本都是引用的是父region的文件reference文件,所以决定对Region分批次去执行Compaction。先找到和删除reference文件,然后再导入reference链接的父region的原始文件,慢慢导入
查找命令
hdfs dfs -ls -R /hbase/data/default/表名 | awk '{print $8}' | grep '\.' | grep -v 'regioninfo' | grep -v 'splits' | grep -v '\.tmp' |
删除这些reference文件,然后根据reference文件命名格式: ‘hfile名.region名’,到父reigon目录下找到对应的HFile。然后创建一个文件夹fileDir,在此文件夹下按照列族名创建列族文件夹,并把上面找到的HFile分别放到对应的列族文件夹中,为LoadIncrementHFiles手工导入HFile做准备
c) 接着分批次使用LoadIncrementHFiles做导入,并手工执行Compact。
hbase org.apache.hadoop.hbase.tool.LoadIncrementHFiles 目录 表名 |
使用该手段是因为当时已经觉得Compaction无法完成可能就是内存不足以一次性将所有的文件合并,所以才采取分段的方式。通过这个方式,这个克隆出来的表的Compaction进度完成了,后续又尝试克隆出来一个新的表,使用相同方式,但换成一次性将文件去导入,结果Compaction又卡住了。
d) 后面把这个克隆出来的表重命名回原来的表,并且把查询业务接入,业务正常,因为该业务使用的图数据引擎JanusGraph,他存放在HBase里的数据都有特定的结构,通过JanusGraph查询接口查询能正常返回,说明数据也都没有乱。
问题原因:
这个问题的触发原因是RS堆内存初始设置比较小,故障前业务比较繁忙,写入的时候,Region发生分裂,并且还在持续写入,需要做Compaction。另外该表使用的GZ压缩算法也对Compaction造成了一定的影响,如果内存稍微大一点,也不会有问题。
问题的疑问:
MAT中显示的ShortCompaction里面那消耗的1.5GB内存,没明白为何会占用那么多,Compaction是读取多个Hfile中最小mvcc的cell,然后对cell使用writer做的append。但是还要消耗这么大的内存是为什么呢,有人能解答这个问题就好了
在社区上找到一个Jira,可能与之有关
https://issues.apache.org/jira/browse/HBASE-22072
https://issues.apache.org/jira/browse/HBASE-22134
- 点赞
- 收藏
- 关注作者
评论(0)