对hbase调优,是很必要的,明显提升响应性能。下面晒下GC调优的成果,是原来CMS GC峰值的10%,历史均值的20%左右 ,调优后GC稳定在200ms左右。
之前是CMS GC不过忘了记录原始的GC配置了。
Parallel GC : Throughput friendly 目前处于维护模式,赶紧放弃吧
CMS GC: low latency for heap < 32GB 将会被G1GC取代
G1 GC: low latency 一键GC 调优,自适应,通用性强。
G1GC 并发标记 ,自动compaction, 调优简单,低延迟+可预测的延迟时间。
下面是采用G1 GC调优之后的结果图,不用说,很犀利。
可以采用 YCSB client进行 各 50%读写压力测试
分时GC时间
目前regionserver 40% BlockCache 40% Memstore .
-XX:+UseG1GC #开启G1GC
-XX:InitiatingHeapOccupancyPercent=70 #当达到heap大小的70%时进行提前启动标记周期进入Mixed GC
-XX:+PrintFlagsFinal -XX:+PrintReferenceGC # 打印GC标识,引用
-XX:+UnlockExperimentalVMOptions -XX:-ResizePLAB # 取消 内存整理,G1GC 天生优势
-XX:G1NewSizePercent=3 # 3-9Minimum size for Eden each epoch, differs by cluster
-XX:MaxGCPauseMillis=200 # 期待的最大停留时间,未必满足
-XX:+UnlockDiagnosticVMOptions
-XX:+G1SummarizeConcMark
-XX:+ParallelRefProcEnabled #Helps keep a lid on reference processing time issues were were seeing
-XX:+PrintGCDetails
-XX:+PrintAdaptiveSizePolicy # 自适应策略,调节Young Old Size
-XX:G1HeapRegionSize=32M # hbase heap > 32G时
-XX:G1HeapWastePercent=20 #Exclude most expensive Mixed GC by increase waste percent (default=5%)
-XX:ConcGCThreads=8 # concurrent marking phase can be completed early enough to avoid full GC
-XX:ParallelGCThreads=13 # 8+(logical_processor -8)*(5/8)
-verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime # 打印应用停留时间
-XX:+PrintTenuringDistribution # 老年代分布
-Xloggc:./region-server-gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=2
-XX:GCLogFileSize=512M
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=22222
借鉴了众多G1GC调优得到的结果。
我在这里所罗列的参数的默认值都是基于JDK8u45,所以可能后续的JDK版本会有些值不一样,这个读者可以直接通过JDK的官方帮助文档获取最新默认值信息。
-XX:+UseG1GC:启用G1 GC。JDK7和JDK8要求必须显示申请启动G1 GC,JDK可能会设置G1 GC为默认GC选项,也有可能会退到早期的Parallel GC,这个也请关注吧,JDK9预计2017年正式发布;
-XX:G1NewSizePercent:初始年轻代占整个Java Heap的大小,默认值为5%;
-XX:G1MaxNewSizePercent:最大年轻代占整个Java Heap的大小,默认值为60%;
-XX:G1HeapRegionSize:设置每个Region的大小,单位MB,需要为1,2,4,8,16,32其一,默认是堆内存的1/2000。前面我们讲过大对象概念,如果这个值设置比较大,那么大对象就可以进入Region了,同样地,这样做的坏处是直接干预了各年龄代的分配大小;
-XX:ConcGCThreads:与Java应用一起执行的GC线程数量。默认是Java线程的1/4。减少这个参数的数值可能会提升并行回收的效率,即提高系统内部吞吐量(系统是一个整体,CPU资源大家都需要占用),不过如果这个数值过低,也会导致并行回收机制耗时加长;
-XX:+InitiatingHeapOccupancyPercent(简称IHOP):G1内部并行循环启动的设置值,默认为Java Heap的45%。这个可以理解为老年代空间占用的空间,GC收集后需要低于45%的占用率。这个值主要是为了决定在什么时间启动老年代的并行回收循环,这个循环从初始化并行回收开始,可以避免Full GC的发生;
-XX:G1HeapWastePercent:G1不会回收的内存大小,默认是堆大小的5%。GC会收集所有的Region,如果值达到5%,就会停下来不再收集了; -XX:G1MixedGCCountTarget:设置并行循环之后需要有多少个混合GC启动,默认值是8个。老年代Regions的回收时间通常比年轻代的收集时间要长一些,所以如果混合收集器比较多,可以允许G1延长老年代的收集时间;
-XX:+G1PrintRegionLivenessInfo:这个参数需要和-XX:+UnlockDiagnosticVMOptions配合启动,这可以理解,它们本身就是属于VM的调试信息。如果开启了,VM会打印堆内存里每个Region的存活对象信息。这个信息在标记循环结束后可以打印出来;
-XX:G1ReservePercent:这个值是为了保留一些空间用于年代之间的提升,默认值是堆空间的10%。注意这个空间保留后就不会用在年轻代了,大家可以看到GC日志里输出显示,我们大量执行的是年轻代回收,所以如果你的应用里面有比较大的堆内存空间、比较多的大对象存活,那还是减少一点保留空间吧,这样会给年轻代更多的预留空间、GC之间更长的处理时间;
-XX:+G1SummarizeRSetStats:这个也是一个VM的调试信息。如果启用,会在VM推出的时候打印出RSets的详细总结信息。如果启用-XX:G1SummaryRSetStatsPeriod参数,就会阶段性地打印RSets信息;
-XX:+G1TraceConcRefinement:这个也是一个VM的调试信息。如果启用,并行回收阶段的日志就会被详细打印出来;
-XX:+GCTimeRatio:大家知道,GC的有些阶段是需要Stop-the-World,即停止应用线程的,这个参数就是计算花在Java应用线程上和花在GC线程上的时间比率,默认是9。这个参数主要的目的是让用户可以控制花在应用上的时间,G1的计算公式是100/(1+GCTimeRatio),这样如果采用9,则最多10%的时间会花在GC工作上面。Parallel GC的默认值是99,表示1%的时间被用在GC上面,这是因为Parallel GC贯穿整个GC,而G1则根据Region来进行划分,不需要全局性扫描Java Heap;
-XX:+UseStringDeduplication:手动开启Java String对象的分割工作,这个是JDK8u20之后新增的参数,主要用于相同String避免重复申请内存,节约Region的使用;
-XX:MaxGCPauseMills:G1停止执行的一个目标值,单位是毫秒,默认是200毫秒,这个值不一定真的会达到。这个参数会通过控制年轻代的大小来实现目标。
在线GC日志分析 http://gceasy.io
在线dump文件分析 http://fastthread.io/
http://blog.jobbole.com/109170/
https://blogs.apache.org/hbase/entry/tuning_g1gc_for_your_hbase
counter