JVM 与 Hbase
前面我们介绍过,G1GC 是现在比较流行的JVM 垃圾回收。所以,我们就结合G1GC 来讨论下Hadoop的GC。
HBase的G1GC
首先,我们本篇文章的主要依据就是官方的blog。https://blogs.apache.org/hbase/entry/tuning_g1gc_for_your_hbase
鉴于已经有官方blog作为资料,并且实验环境并不是很充足,所以我们直接叙述结论。
参数配置
首先看下,我们实际工作中的HBase的参数配置。以及各项参数的实际含义。
参数 | 含义 |
-XX:+UseG1GC | 显式地要求使用G1 GC |
-Xms64G | 设置JVM初始堆内存为64G |
-Xmx64G | 设置JVM最大可用内存为64G |
-XX:PermSize=256m | JVM初始分配的非堆内存 |
-XX:G1NewSizePercent=4 | 新生代最小值,默认值5% |
-XX:MaxGCPauseMillis=200 | 设置G1收集过程目标时间,默认值200ms,不是硬性条件 |
-XX:ParallelGCThreads=16 | STW期间,并行GC线程数 |
-XX:MaxTenuringThreshold=4 | 年龄阈值,默认15(对象被复制的次数) |
-XX:+UnlockExperimentalVMOptions | 与+UseG1GC 一起使用,来解锁参数,应该是一种安全机制 |
-XX:+ParallelRefProcEnabled | 默认为false,并行的处理Reference对象,如WeakReference,除非在GC log里出现Reference处理时间较长的日志,否则效果不会很明显。 |
-XX:-ResizePLAB | 是否启动动态修改 |
如何调整HBase集群
开始之前: GC and HBase monitoring
可以使用任何工具跟踪收集 block cache
, memstore
和 static index size
这些指标,可以从 RegionServer JMX metrics
中找到。
“memStoreSize”
“blockCacheSize”
“staticIndexSize”
还可以使用官方的 collectd
插件来跟踪一段时间内的G1GC性能,并使用 gc_log_visualizer
来了解特定的GC日志。要使用这些内容就要在 RegionServers 上跟踪这些信息。
-Xloggc:$GC_LOG_PATH
-verbosegc
-XX:+PrintGC
-XX:+PrintGCDateStamps
-XX:+PrintAdaptiveSizePolicy
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintTenuringDistribution
还建议使用某种GC日志轮换,例如:
-XX:+ UseGCLogFileRotation
-XX:NumberOfGCLogFiles = 5
-XX:GCLogFileSize = 20M
Step 0:推荐默认值
建议将以下JVM参数和值作为HBase RegionServers的默认值:
-XX:+ UseG1GC
-XX:+ UnlockExperimentalVMOptions
-XX:MaxGCPauseMillis = 50
-XX:-OmitStackTraceInFastThrow
-XX:ParallelGCThreads = 8+(逻辑处理器-8)
-XX:+ ParallelRefProcEnabled
-XX:+ PerfDisableSharedMem
-XX:-ResizePLAB
Step 1:确定预期的HBase最大使用率
使用上面提到的RegionServer JMX指标,查找整个集群中每个指标的最大值
Maximum block cache size.
Maximum memstore size.
Maximum static index size.
将每个最大值扩展到 110%,以适应最大使用值的轻微增幅。这是该指标的使用上限: 例如最大10 GB记录的memstore→11 GB memstore上限.
理想情况下,在过去一周或一个月内跟踪这些指标,就可以找到该时间段内的最大值。如果不是,在计算 memstore和static index size 上限时要比110% 更高一些。尤其是 Memstore,随着时间的推移,可能会变的更大。
Step 2: 设置堆大小,IHOP和Eden大小
先从比较低的 Eden 大小开始设置:如果不是很确定,8% 的堆的大小就可以。
增加Eden大小会增加单个GC pause 时间,但会略微减少GC中花费的总时间。
减小Eden大小会产生相反的效果:GC pause 时间越短,GC中的总体时间略长。
用Step 1中的Eden大小和使用上限确定必要的堆大小:
Heap ≥ (M + B + O + E) ÷ 0.7
M = memstore cap, GB
B = block cache cap, GB
O = static index cap, GB
E = Eden size, GB
根据计算的值设置固定堆大小的JVM参数,例如:
根据使用上限和堆大小在JVM中设置IHOP:
IHOP = (memstore cap’s % heap + block cache cap’s % heap + overhead cap’s % heap + 20)
-XX:InitiatingHeapOccupancyPercent = IHOP
Step 3:根据使用上限调整HBase配置
根据使用上限和总堆大小,在 HBase 配置中设置 block cache
上限 和 memstore
上限比率:
hfile.block.cache.size → block cache cap ÷ heap size
hbase.regionserver.global.memstore.size → memstore cap ÷ heap size
Step 4: 配置其他建议的参数以提高GC的性能
-XX:MaxTenuringThreshold = 1
-XX:G1HeapWastePercent = 10
-XX:G1MixedGCCountTarget = 16
-XX:G1HeapRegionSize = #M #必须是2的幂,在[1..32]范围内,理想情况下,#是这样的:堆大小÷#MB = 2048个region。
Run it
应用这些配置,然后重启RegionServers,看看他们的表现。
可以如上所述调整Eden大小,以优化较短的单个GC或减少GC中的总时间,如果这样做,请确保Eden +IHOP≤90%。
如果HBase客户端可能有非常突发的流量,可以考虑在IHOP和Eden之外添加堆空间(例如,IHOP + Eden加起来高达80%.
其他参考
Last updated