背景介绍
3台regionserver,3台zookeeper,master单节点(master2未启动),实时处理程序,实时向HBase表写数据,Hbase集群于hdfs、hive、调度系统公用,集群上每天凌晨0点至上午10点跑10小时左右的调度任务。
问题现象
Regionserver经常出现宕机事件
Master standby停机
推测原因&分析
1、compaction、split过于频繁
Hbase0.94以后hfile最大文件配置hbase.hregion.max.filesize=10G。
Region大小与集群支持的总数据量大小有关,如果总量太小,单个region太大,不利于并行数据处理;如果集群需支持的总数据量比较大,region太小,则会导致region的个数过多,导致region的管理、split等成本过高;
我们一个RS配置的磁盘为16T数据量,数据replica=3,则一台RS可以存储5T数据量,如果每个region最大为10G,则最多500个region。
Hbase通过split 实现水平sharding,但是在split过程中旧region会下线,新region还会做compaction,中间有一段时间大量数据不能被读写,这对于online是不能忍受的。
如果要自己管理region的split,可再调大该值,并且在建表的时候规划好region数量和rowkey设计;进行region预建做到一定时间内,控制每个region的数据大小在一定的数据量之下。另外,一般在线服务的hbase集群都会弃用hbase的自动split,转而自己管理split。禁止自动split&compaction(默认7天),在集群空闲期(白天)执行手动split(通过脚本实现)。
2、Hdfs压力过大,datanode、regionserver超负荷
由于集群运行各种任务,hdfs读写压力大,datanode的负载比较高,导致regionserver写hdfs异常,宕机
2017-03-30 02:25:54,414 WARN org.apache.hadoop.hdfs.DFSClient: Slow ReadProcessor read fields took 65021ms (threshold=30000ms); ack: seqno: -2 reply: 0 reply: 1 downstreamAckTimeNanos: 0, targets: [DatanodeInfoWithStorage[192.168.2.62:50010,DS-a98bc32d-0b3a-4cf2-b17b-b1a24badb9b4,DISK],DatanodeInfoWithStorage[192.168.2.64:50010,DS-82640457-7b92-4347-b0a8-7405804117eb,DISK]] 2017-03-30 02:25:54,417 WARN org.apache.hadoop.hdfs.DFSClient: DFSOutputStream ResponseProcessor exception for block BP-305404928-192.168.2.60-1477041256525:blk_1082088790_8349147java.io.IOException: Bad response ERROR for block BP-305404928-192.168.2.60-1477041256525:blk_1082088790_8349147 from datanode DatanodeInfoWithStorage[192.168.2.64:50010,DS-82640457-7b92-4347-b0a8-7405804117eb,DISK] at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer$ResponseProcessor.run(DFSOutputStream.java:1022)2017-03-30 02:25:54,418 WARN org.apache.hadoop.hdfs.DFSClient: Error Recovery for block BP-305404928-192.168.2.60-1477041256525:blk_1082088790_8349147 in pipeline DatanodeInfoWithStorage[192.168.2.62:50010,DS-a98bc32d-0b3a-4cf2-b17b-b1a24badb9b4,DISK],DatanodeInfoWithStorage[192.168.2.64:50010,DS-82640457-7b92-4347-b0a8-7405804117eb,DISK]: bad datanode DatanodeInfoWithStorage[192.168.2.64:50010,DS-82640457-7b92-4347-b0a8-7405804117eb,DISK]
当前hbase运行模式(hbase.cluster.distributed)默认false为单机模式。应设置为true,开启分布式模式.
DataNode 的 Java 堆栈大小(字节)为1G,建议2G.
HBase Master 的 Java 配置选项 & HBase RegionServer 的 Java 配置选项
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled
修改:
Master: -Xms4g -Xmx4g -Xmn1g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:PermSize=128m -XX:MaxPermSize=128m Region Server: -Xms20g -Xmx20g -Xmn4g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:PermSize=128m -XX:MaxPermSize=128m -XX:MaxDirectMemorySize=16G -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError
3、blockingStoreFiles设置不合理
日志中频繁出现”has too many store files;delaying flush up to 90000ms”
2017-03-25 03:48:07,940 WARN org.apache.hadoop.hbase.regionserver.MemStoreFlusher: Region f_acct_idtfno_map,430122197005187122A104727411600019,1481553873843.1611e051523f8955b80d7b8012ca4960. has too many store files; delaying flush up to 90000ms 2017-03-25 03:48:08,356 INFO org.apache.hadoop.hbase.regionserver.DefaultStoreFlusher: Flushed, sequenceid=562745, memsize=130.9 M, hasBloomFilter=true, into tmp file hdfs://nameservice1/hbase/data/default/f_acct_idtfno_map/1f70d611178c72de82fa5493dbd0772b/.tmp/6e35b0fe71b34f23aa0694a471050f5a 2017-03-25 03:48:08,370 INFO org.apache.hadoop.hbase.regionserver.HStore: Added hdfs://nameservice1/hbase/data/default/f_acct_idtfno_map/1f70d611178c72de82fa5493dbd0772b/f/6e35b0fe71b34f23aa0694a471050f5a, entries=677274, sequenceid=562745, filesize=49.6 M 2017-03-25 03:48:08,372 INFO org.apache.hadoop.hbase.regionserver.HRegion: Finished memstore flush of ~130.90 MB/137260672, currentsize=11.55 MB/12110752 for region f_acct_idtfno_map,432426391218237A101248659100020,1481653983532.1f70d611178c72de82fa5493dbd0772b. in 2659ms, sequenceid=562745, compaction requested=true
Hbase配置hbase.hstore.blockingStoreFiles=10(默认)。
如果任何一个store的storefile文件数大于该值,则在flush memstore前先进行split或者compact,同时把该region添加到flushQueue中,延时刷新,这期间会阻塞写操作知道compact完成或者超过hbase.hstore.blockingWaitTime(默认90s)。
建议:为避免memstore不及时flush,该值需要上调,具体值可以在测试环境评估及压测后上线。
4、GC回收时Jvm不够
每天Jvm间隔一段时间就会停顿短则几秒,长可达20s,甚至30s,日志见下:
2017-03-30 02:24:11,370 INFO org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 7478ms No GCs detected 2017-03-30 02:21:12,805 WARN org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 10286ms GC pool 'ParNew' had collection(s): count=1 time=10466ms 2017-03-30 02:27:04,086 WARN org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 23505ms No GCs detected 2017-03-28 02:09:24,442 WARN org.apache.hadoop.hbase.util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 39933ms No GCs detected
查看Regionserver中heapsize设置为32G,hfile.block.cache.size=0.4,使得block size=heapsize * hfile.block.cache.size *0.85=10.88G
由此可以block cache发生了CMS GC。目前使用的BlockCache优点是直接采用jvm提供的HashMap来管理Cache,简单可依赖;内存用多少占多少,JVM会帮你回收淘汰的BlOCK占用的内存。缺点更明显:
a.一个Block从被缓存至被淘汰,基本伴随着Heap中的位置从New区晋升到Old区
b.晋升在Old区的Block被淘汰后,最终由CMS进行垃圾回收,随之带来的是Heap碎片 ,old 区域变大导致cms 时间过长。
c.因为碎片问题,随之而来的是GC时晋升失败的FullGC,我们的线上系统根据不同的业务特点,因为这个而发生FullGC的频率,有1天的,1周的,1月半年的都有。对于高频率的, 在运维上可以通过在半夜手工触发FullGC来缓解
d.如果缓存的速度比淘汰的速度快,很不幸现在的代码有OOM的风险(这个可以修改下代码避免)
Hbase0.94+提供了BucketCache,一方面可以降低regionserver heapsize的大小,降低cms发生的几率和减少时间;另一面可通过利用BucketCache增加二级缓存,来利用off heap cache,当然也可以将现有数据盘更换为SSD来做二级缓存。
Hbase-site.xml
<property> <name>hbase.bucketcache.ioengine</name> <value>offheap</value> </property> <property> <name>hbase.bucketcache.percentage.in.combinedcache</name> <value>0.8</value> </property> <property> <name>hbase.bucketcache.size</name> <value>16384</value> </property>
增加读缓存后,也可以提高data block的命中率。当前集群regionserver缓存命中率平均<50%,截图见下:
参考资料
http://hbase.apache.org/book.html#hbase_default_configurations