导语:
近期腾讯云的一家大客户频繁出现 HBase regionserver 挂掉, 影响业务正常使用. 通过调整堆栈大小, gc 优化, 超时时间等都无法解决该问题. 经过细致并综合分析 hbase regionserver,hbase master 以及 zookeeper 的日志, 发现了问题所在: tickTime 设置导致 hbase 超时时间错误.
一, 故障现象
1, 首先 regionserver 频繁爆出两类错误:
wal.FSHLog: Error syncing, request close of WAL:
以及出现错误:
regionserver.MemStoreFlusher:Cache flush failed for region XXX ......
2, 然后出现 regionserver 死亡错误:
HBase error : Memstore size is xxxxxx
以及出现 regionserver dead 故障:
Region server exiting
java.lang.RuntimeException: HRegionServer Aborted
二, 故障分析与解决
从上述报错可以看出, 引起 regionserver 故障的主要原因集中在 memstore, 因此首先想到是 regionserver 的堆栈设置不合理或者是 gc 优化不合理. 因此, 我们将 hbase 以及 regionserver 的堆栈都设置为 16G, 然后对 gc 进行优化. 最终, HBase 具体优化参数如下所示:
export HBASE_HEAPSIZE=16384
export master_heapsize=8192
export regionserver_heapsize=16384
export HBASE_OPTS="$HBASE_OPTS -Xss512k -XX:PermSize=256m -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -XX:GCPauseIntervalMillis=100 -XX:-OmitStackTraceInFastThrow -XX:MaxTenuringThreshold=1 -XX:ConcGCThreads=12 -XX:G1OldCSetRegionThresholdPercent=3 -XX:ParallelGCThreads=18 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+ParallelRefProcEnabled -XX:-ResizePLAB -XX:G1MixedGCCountTarget=16 -XX:InitiatingHeapOccupancyPercent=75 -XX:G1ReservePercent=5 -XX:G1NewSizePercent=8 -XX:G1HeapRegionSize=16m -XX:ErrorFile={{log_dir}}/hs_err_pid%p.log"
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -Xmx{{master_heapsize}} -XX:PermSize=256m -XX:MaxPermSize=256m"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:CMSInitiatingOccupancyFraction=70 -Xms{{regionserver_heapsize}} -Xmx{{regionserver_heapsize}}"
经过参数优化之后, regionserver 频繁挂掉的情况有所改善.
但是, regionserver 还是出现了挂掉的情况, 只是比之前有改善. 因此通过优化堆栈以及 gc, 并不能完全解决该问题.
三, 分析故障原因
既然通过优化 hbase 本身无法解决 regionserver 频繁挂掉的原因, 那就必须将分析扩大到 hbase 相关的进程. 与 hbase 密切相关的是 zookeeper. 我们详细分析看 zk 的日志, 比如之前 regionserver 在 03:03:17 时间出现了 regionserver dead 报错信息, 因此我们分析 zk 在这个时间段前后的日志. 从日志看到 regionserver 与 zk 的超时时间是 40 秒,"the sessions negotiated with zookeeper from dead regionserver were of 40s". 然后再查看 regionserver 的 gc 时长, 确实超过了 40 秒.
总结原因:
(1)gc 时间过长, 超过 40 秒的 maxSessionTimeout 时间, 使得 zk 认为 regionserver 已经挂掉 dead;
(2)zk 返回 dead region 到 master,master 就让其他 regionserver 负责 dead regionserver 的 regions;
(3) 其他 regionserver 会读取 wal 进行恢复 regions, 处理完的 wal, 会把 wal 文件删除;
(4)dead regionserver 的 gc 完成, 并且恢复服务之后, 找不到 wal, 已经产生上面截图中的报错 (wal.FSHLog: Error syncing, request close of WAL);
(5)dead regionserver 从 zk 得知自己 dead, 就关闭自己 (Region server exiting,java.lang.RuntimeException: HRegionServer Aborted)
四, 最终原因: tickTime 超时
经过上面的分析, 是 gc 时间超过 40 秒的 maxSessionTimeout 导致的 regionserver 挂掉. 但是, 我们就很纳闷了, 因为我们设置的 zookeeper.session.timeout 超时时间为 240 秒, 远远超过 40 秒时间. 非常奇怪呀!
经过 hbase 社区求助, 以及 google 类似的问题, 最终找到原因 (
详细链接, 请参考: https://superuser.blog/hbase-dead-regionserver/
):
原来我们的 HBase 并没有设置 tickTime, 最终 hbase 与 zk 的会话最大超时时间并不是 zookeeper.session.timeout 参数决定的, 而是有 zk 的 maxSessionTimeout 决定. zk 会根据 minSessionTimeout 与 maxSessionTimeout 两个参数重新调整最后的超时值, minSessionTimeout=2*tickTime, maxSessionTimeout=20*tickTime. 我们的大数据集群, zk 的 tickTime 设置为默认值 (2000ms)2 秒, 因此, 最终 hbase 与 zk 的超时时间就为 40 秒.
经过调整 zk 的 tickTime 为 6 秒, 相应的 zookeeper.session.timeout 为 120 秒, 最终解决 regionserver 频繁挂掉的故障.
来源: https://cloud.tencent.com/developer/article/1030070