HBase-GC性能优化

1 JVM调优

1.1 堆内存

默RegionServer的堆内存为1G,这里Memstore默认站40%,也就是400M,在实际场景中很容易因为Memstore太小导致阻塞,修改参数,在cong/hbase-env.sh:

export HBASE_HEAPSIZE=8G

该参数会将Master和RegionServer的堆内存都设置为8G,所以有需要的话尽量使用专用的堆内存设置项:

export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -Xms4g -Xmx4G"
export HBASE_REGIONsERVER_OPTS="$HBASE_REGIONSERVER_OPTS -Xms8g -Xmx8G"

就可以将Master调整为4G,RegionServer调整为8G。需要注意的是,不管在什么时候都必须保证物理机留有10%的内存给操作系统做必要的操作。一般来说,如果物理机上还有计算框架,那么RegionServer的内存占有率应该是计算框架之外最大的。
还需要注意的是,如果JDK版本低于8,HBase会有一个内存泄漏的Bug,永久对象区(Permanent Generation,这个区域在非堆内存里边)必须这只如下项:

export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -xx:PermSize=128m -XX:MaxPermSize=128m"
export HBASE_REGIONsERVER_OPTS="$HBASE_REGIONSERVER_OPTS -xx:PermSize=128m -XX:MaxPermSize=128m"

如果Xmx调的比较大了,那么需要把PermSize和maxPermSize调整的都大一些(一般不会出现这种情况,128M已经够大了)。JDK8+就不需要这个操作了。

1.2 Full GC的影响

一般来说RegionServer的堆内存越大越好,但是因为垃圾回收的缘故,内存大了之后,相应的FullGC时间也会线性增加,一般来说每G的内存需要的FullGC时间为:。FullGC优势可能达到好几分钟,这个阶段会停止响应任何请求,相当于所有线程挂起,这种暂停又叫做Stop-The-World(STW),FullGc的对HBase造成严重后果比较严重:
在Zookeeper检测RegionServer心跳包的时候,RegionServer正在FullGc无法回应,而如果超过阀值等待时间会被标记为宕机,这时候会将该RegionServer上的数据向其他RegionServer迁移,并且该RegionServerFullGc结束后发现自己被宕机了,为了防止脑裂,会停止自己(RegionServer自杀,又叫朱丽叶暂停)。很多场景下会将zookeeper的心跳检测阀值调大,但是这并不可取。
GC回收策略优化
为了避免长时间FullGC或者减少FullGc的发生,JVM提供了四中GC回收器:

  • 串行回收器:SerialGC
  • 并行回收器:ParallelGC 注重高吞吐量
  • 并发回收器:ConcMarkSweepGC简称CMS 注重低延迟
  • G1GC回收器:Garbage-First GC 吸收了并发和并行回收的特长

1.2.1 ParallelGC和CMS组合方案

并行回收器的性能没有串行回收器好但是FullGC时间较短;而并发回收器主要可以减少老年代的暂停时间,并且可以保证不停止的情况下进行收集,但是每次回留下一些“浮动垃圾”,只能在下次回收的时候被回收。所以Hbase比较符合的配置是:

  • 年轻代使用并行回收器ParNewGC
  • 老年代使用并发回收器ConcMarkSweepGC

依旧在conf/hbase-env.sh,如果需要修改Master的,将RegionServer修改为Master即可:

export HBASE_REGIONsERVER_OPTS="$HBASE_REGIONSERVER_OPTS -Xmx8g -Xms8g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC"

1.2.2 G1GC回收方案

G1GC是在JDK1.7.0_O4(jdk7 update4)中新增的,并且如果RegionServer内存很大,大于4G的话就可以考虑G1GC。之所以引入了G1GC,是因为CMS回收依旧不能避免FullGC,发生在如下两种情况:

  • 在CMS工作时候,一些对象经过了多轮幸存,从年轻代移动到了老年代,但是老年代已经空间不足,就回引发STW,暂停,JVM整体又不能响应任何请求了。

  • 当回收回来的内存太细碎,导致新对象放不进去,也只好触发FullGC来整理空间
    G1GC会申请一大块连续的内存空间装在JVMHeap,并被分割成JVM的一个个Region(并不是HBase定义的Region),然后对各个Region单独进行GC,就可以最大限度的避免(不能完全避免)FullGC,并且可以通过手动指定MaxGCPauseMills参数来空值一旦发生FullGC的时候最大的暂停时间,避免时间太长造成的RegionServer自杀:

    export HBASE_REGIONSERVER_OPTS="HBASE_REGIONSERVER_OPTS -Xms24g -Xms24g -XX:+UseG1GC -XX:MaxGCPauseMillis=100"
    G1GC适合很大的堆内存情况,这里所说的很大指32G、64G以上,如果RegionServer的堆内存设置为4G-32G,需要手动测试才知道G1GC是否适合,手动实验的时候,记得把调试参数加上:

    分别打印GC详细信息、GC时间、survive空间占用日志

    -XX:+PrintGCDetails -XX:PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy
    其他调优参数:

    -XX:+UseG1GC #使用G1GC
    -Xms100g -Xmx100g #堆内存范围,这里写死为100G
    -XX:MaxGCPauseMills=100 #G1GC最大的GC时间毫秒
    -XX:ParallelRefProcEnabled #GC使用多线程在Young和mixed GC期间处理增加的引用
    -XX:PaarallelGCThreads=8+(logical processors-8)(5/8) # 多线程回收策略,这里logical processors为40
    -XX:-ResizePLAB #开启线程较多时候,该项可以关闭PLAB的大小调整,避免大量线程通信导致的性能下降
    -XX:G1NewSizePercent=5 #年轻代最小值(占堆内存的比例),默认5%
    -XX:G1NewSizePercent=3 #32GHeap
    -XX:G1NewSizePercent=2 #64GHeap
    -XX:G1NewSizePercent=1 #100G+Heap
    控制年轻代大小的关键是保证其在1G的范围,因为测试发现G1清理Eden空间的速度是每1GB使用100ms
    补充一个HBase的GC测试:针对HBase的Java GC调优

1.3 Memstore的专属JVM策略MSLAB

堆内存非常大的时候,FullGC时间非常长,此时解决FullGC问题不能完全依靠JVM自身的垃圾回收器,MSLAB是为MemStore专门设计的内存管理策略,对标CMS。采用CMS发生FullGC的原因主要有;

  • 并发标记失败(concurrent mode failure):如果在CMS还没有将垃圾回收完成,空间没有完全释放,这个时候新生代的对象过快转化为老年代的对象时候,发现老年代的空间不够了,此时垃圾回收会放弃并发回收转而使用单线程的STW,回到了FullGC。该过程可以通过设置-XX:CMSInitiatingOccupancyFraction=N来缓解,N表示单次JVM启动垃圾回收时候堆内存占用的百分比,设置的越小,垃圾回收越早启动,一般设置为70。
  • 碎片化导致的失败(Promotion Failure due to Fragmentation):当前要从新生代提升到老年代的对象比老年代所有的碎片空间都要大,也会触发STW进行FullGC。这个情况无论怎么调整上述的CMSInitiatingOccupancyFraction都是无法解决的,因为CMS只做标记回收不会合并整理,只要RegionServer启动的时间够长一定会导致FullGC。

之所以会出现碎片内存空间,是因为MemStore定期刷写为一个HFile,刷新完成后Memstore所占用的空间就会被回收, 但是因为内存分配都是顺序分配的,导致逐渐出现Memstore位置为碎片空间,产生不连续内存。直到没有任何一块连续内存不能存放新的数据,JVM只好进行STW,使用单进程进行内存空间重新排列。

1.3.1 LTAB方案

不过JVM为了解决碎片内存问题,有一个TLAB(Thread-Local allocation buffer)方案,每个线程都会分配一个固定大小的内存空间,专门给这个线程使用,用完之后释放,新线程也会申请这么大的空间,就不会出现碎片空间。明显的缺点是,如果线程中的对象不需要占用整个线程申请的对象会导致很大的内存浪费闲置,内存空间利用率降低,但是为了避免FullGC还是可以考虑的。
但是HBase不能直接使用该方案,因为HBase的多个Region是被一个线程管理的,多个Memstore占用的空间不能合理分开,于是HBase基于TLAB实现了MSLAB。

1.3.2 MSLAB-Memstore-Local Allocation BUffers

MSLAB完全按照TLAB实现思路,只不过内存是由Memstore来分配的,实现思路为:

  • 引入了chunk的概念,chunk就是一块内存,大小默认为2M
  • RegionServer维护者一个全局的MemStoreChunkPool实例,是一个chunk池
  • 每个MemStore实例中有一个MemStoreLAB实例
  • 当MemStore接收到KeyValue数据的时候先从ChunkPool中申请一个chunk,然后将数据放到chunk中。
  • 如果chunk放满了,新申请一个chunk
  • 如果Memstore因为刷写释放了内存,则按chunk为单位清空内存

堆内存按照chunk为单位划分为规则空间,消除了碎片空间导致的无法插入数据的问题,但是有时候只写入1kB数据也需要2M的chunk空间,但是可以容忍。相关参数如下,在hbase-site.xml中配置:

#设置为true,打开MSLAB,默认为true
hbase.hregion.memstore.mslab.enabled
#每个chunk大小,默认2MB,2048*1024B
hbase.hregion.memstore.mslab.chunksize
#能放入chunk的最大单元格大小,默认为256K
hbase.hregion.memstore.mslab.max.allocation
#在整个memstore可以占用的堆内存中,chunkPool占用的比例,默认为0.0,最大1.0
hbase.hregion.memstore.chunkpool.maxsize
#在RegionServer启动的时候可以预分配一些空的chunk出来放到chunkPool中待使用,改制代表了预分配的chunk占总的chunkPool比例,默认为0.0,最大1.0
hbase.hregion.memstore.chunkpool.initialsize

MSLAB使用注意事项
MSLAB可以和G1GC一起使用,没有冲突。不过看起来MSLAB和G1的实现思路很接近,其实G1是后来才出现的策略,并且根据测试,结合使用的性能会更高。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容