现象:因为系统实时性要求比较高,HBase超时时间设置为2秒。偶尔会出现(几个小时)出现一波超时的情况,看了监控IO、CPU等并没有出现明显大波动。不过集群是高读写的,每秒几万的请求。就开始参与协助帮忙集群的排查、调优工作。
汗,最关键的是集群都用上了SSD,这是开大的节奏。
先来看看HBase主要的几个参数:
1、major compaction(大合并操作,几天执行一次,或者手动执行。对IO影响很大,对性能影响也很大)
2、memstore:regions数量、列簇数量有影响 ,一个列簇就需要一个memstore ,会占用region server的内存。
3、负载均衡:是不是某几台机器负载特别不均衡,请求倾斜严重等?
大家遇到的主要问题无非是Full GC异常导致宕机问题、RIT问题、写吞吐量太低以及读延迟较大。
flushQueueLength,从监控来看队列大部分时间保持为0,说明集群刷写的速度跟的上。
blockcache命中率等指标也正常。
听到集群每个节点才配置8G内存,这么多读写。感觉配置可能有点不对。就开始排查是否GC影响,开始加上详细的打印日志。内存不足容易导致晋级失败等等,实时性下降。
控制台可以看出每台服务器regions的数量是450-500之间,官方建议每台服务器200个region以内,最好100个左右。但其实400-500也无妨。
因为每个Rergion每个Family就算不写数据,的MemStore本地缓存需要2M,如果500个regions和1个family,就算不存储任何数据也要1G左右的堆内存空间。
通过公式:
((RS Xmx) hbase.regionserver.global.memstore.upperLimit) / (hbase.hregion.memstore.flush.size (# column families))
=8G 0.4 / 128m 1 = 支持26个family频繁写入
通过增加GC的详细日志可以看出偶尔会出现晋级失败等情况。
最低CMS垃圾回收压缩后的内存至少需要6.5G,memstore可能需要3.5G ,控制台看出blockcached 也需要3.5G,预留2G给新生代,所以就给内存配置了18G。
总结下GC容易出现:
一.并发模式失败(concurrent mode failure)
行CMS GC的过程中同时业务线程将对象放入老年代,而此时老年代空间不足,这时CMS还没有机会回收老年带产生的,或者在做Minor GC的时候,新生代救助空间放不下,需要放入手游购买老年带,而老年带也放不下而产生的。
二. 提升失败(promotion failed)
在 Minor GC 过程中,Survivor Unused 可能不足以容纳 Eden 和另一个 Survivor 中的存活对象, 那么多余的将被移到老年代, 称为过早提升(Premature Promotion)。 这会导致老年代中短期存活对象的增长, 可能会引发严重的性能问题。 再进一步, 如果老年代满了, Minor GC 后会进行 Full GC, 这将导致遍历整个堆, 称为提升失败(Promotion Failure)。
根据几次日志调整NewSize以及Survivor、Heap大小以后,就开始比较稳定,几乎没有出现超时等情况。
总结:
从HHBase控制台首页明显看出很多东西:
1、内存使用情况
2、读写占比情况
3、Num. Stores情况
等等,有很多帮助,请多多留意。
当然当磁盘IO很重时,JVM可能会被阻挡相当长的时间,解决方案应该是通过将服务器上面一些日志文件放在单独的HDD或高性能磁盘(如SSD)上来避免IO争用。