订阅更新

线上Spark Executor用的G1还是CMS?——垃圾回收器选型和调优

Java手册 第 2 题 约 8 分钟读完

本文目录
  1. 先说结论
  2. 主流GC收集器对比
  3. G1收集器——大数据场景的最佳选择
  4. CMS为什么被淘汰了?
  5. 大数据组件的GC配置实战
  6. 实战踩坑:CMS Concurrent Mode Failure导致Executor被kill
  7. ZGC——未来的方向
  8. 面试高频追问
  9. 总结

先说结论

2026年大数据场景推荐G1收集器。G1在JDK 9+是默认GC,兼顾吞吐量和低延迟,对大堆内存友好。CMS已经在JDK 14被移除了。ZGC是未来方向(毫秒级暂停)但还不够成熟。Flink官方推荐G1,Spark 3.x+默认G1,Kafka建议G1。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

GC收集器选型是大数据面试的高频题。在某知名出海硬件品牌用EMR时,Spark作业默认用的是CMS收集器。有一次一个大Shuffle作业频繁报'ExecutorLostFailure',排查发现是CMS的并发失败(Concurrent Mode Failure)导致退化为Serial GC,暂停了15秒,YARN以为Executor挂了直接kill掉。改成G1后问题解决了。面试官问GC收集器,本质上是在考你对不同GC算法的理解和实际调优经验。

主流GC收集器对比

收集器算法暂停时间吞吐量适用堆大小JDK状态
Serial单线程复制/标记整理最长低小堆(几百MB)存在
Parallel(PS+PO)多线程复制/标记整理较长最高中等堆(1-4GB)JDK8默认
CMS并发标记-清除较短中等中等堆JDK14移除
G1分区+并发标记+复制可控(目标200ms)高大堆(4GB+)JDK9+默认
ZGC染色指针+读屏障极短(1-2ms)高超大堆(TB级)JDK15+可用

G1收集器——大数据场景的最佳选择

G1(Garbage-First)把堆分成大小相等的Region(默认2048个),每个Region可以是Eden、Survivor、Old或Humongous(大对象)。G1的核心优势是可以设置暂停时间目标(-XX:MaxGCPauseMillis),G1会自动调整回收策略来尽量满足目标。

# G1的工作方式
#
# 1. 把堆分成2048个等大的Region(默认)
#    每个Region大小 = 堆大小 / 2048
#    8GB堆:每个Region约4MB
#
# 2. Young GC:回收所有Eden和Survivor Region
#    和传统Young GC类似,复制算法
#    但可以动态调整Young区的Region数量
#
# 3. Mixed GC(G1特有):
#    同时回收Young Region和部分Old Region
#    优先回收'垃圾最多'的Region(Garbage-First名字由来)
#    避免了CMS那样的Full GC
#
# 4. 只有在极端情况下才会退化为Full GC
#    比如分配速度远超回收速度
#    G1的Full GC是单线程的,非常慢——要尽量避免

CMS为什么被淘汰了?

CMS(Concurrent Mark Sweep)曾经是低延迟GC的首选,但有三个致命缺点:

① Concurrent Mode Failure:CMS的Old区回收是并发的(和应用线程同时运行),但如果回收速度跟不上对象分配速度,Old区满了就会退化为Serial GC——暂停时间从几十毫秒暴增到十几秒。这就是我在出海硬件品牌遇到的问题。

② 内存碎片:CMS使用标记-清除算法,不做内存整理,会产生内存碎片。碎片多了大对象分配不了,也会触发Full GC。

③ 对CPU不友好:CMS的并发标记阶段会占用CPU资源,在CPU密集型的大数据场景下和业务线程抢CPU。

大数据组件的GC配置实战

# Flink TaskManager(官方推荐G1)
env.java.opts.taskmanager: >-
  -XX:+UseG1GC
  -XX:MaxGCPauseMillis=100
  -XX:G1HeapRegionSize=16m
  -XX:+ParallelRefProcEnabled
  -XX:+PrintGCDetails
  -XX:+PrintGCDateStamps
  -Xloggc:/opt/flink/log/gc.log
 
# Spark Executor
spark.executor.extraJavaOptions=
  -XX:+UseG1GC
  -XX:MaxGCPauseMillis=200
  -XX:InitiatingHeapOccupancyPercent=35
  -XX:G1HeapRegionSize=16m
 
# Kafka Broker
export KAFKA_JVM_PERFORMANCE_OPTS="
  -XX:+UseG1GC
  -XX:MaxGCPauseMillis=20
  -XX:InitiatingHeapOccupancyPercent=35
  -XX:G1HeapRegionSize=16m"
 
# 关键参数说明:
# MaxGCPauseMillis: 目标暂停时间(Flink 100ms,Kafka 20ms)
# InitiatingHeapOccupancyPercent: 老年代占比超过此值触发并发标记
# G1HeapRegionSize: Region大小(堆大时调大到16-32m)

实战踩坑:CMS Concurrent Mode Failure导致Executor被kill

在某知名出海硬件品牌,有一个大Shuffle的Spark作业(处理设备激活数据,Shuffle数据量约50GB)。Executor配了8GB堆内存,用的CMS收集器。

症状:作业跑到Shuffle阶段频繁报ExecutorLostFailure,日志里看到'Container killed by YARN for exceeding memory limits'。但Executor的堆内存明明还有余量。

排查:看GC日志发现CMS发生了Concurrent Mode Failure——Old区回收速度跟不上Shuffle阶段大量中间对象的产生速度,CMS退化为Serial GC,暂停了15秒。15秒内Executor没有响应YARN的心跳,被YARN判定为Dead直接kill。

解决:把CMS改成G1(-XX:+UseG1GC -XX:MaxGCPauseMillis=200),G1的Mixed GC可以分批回收Old区,不会一下子暂停十几秒。改完后Executor再也没被kill过。

ZGC——未来的方向

ZGC(Z Garbage Collector)是JDK 15+引入的下一代GC,最大特点是暂停时间控制在1-2毫秒(不管堆多大)。原理是用染色指针(Colored Pointer)和读屏障(Load Barrier)实现几乎全程并发的GC。

大数据场景的前景:ZGC特别适合对延迟敏感的场景——比如Flink的实时处理、Kafka的低延迟消息。但目前ZGC还不够成熟:① 吞吐量比G1略低(约5-10%);② 不是所有JDK版本都支持;③ 大数据组件官方还没有全面推荐。建议关注但暂时不急着在生产环境切换。

面试高频追问

追问一:G1的MaxGCPauseMillis设多少合适?

取决于应用对延迟的容忍度。Flink建议100-200ms(Checkpoint和Barrier传递需要低延迟);Spark建议200-500ms(批处理对延迟没那么敏感);Kafka建议20ms(消息延迟敏感)。设太低G1会频繁GC(每次回收少量Region),吞吐量下降;设太高GC暂停时间长,影响业务。

追问二:InitiatingHeapOccupancyPercent(IHOP)设多少?

默认45%,大数据场景建议调到30-35%。IHOP控制的是'Old区占比超过多少时启动并发标记'。设低了提前启动并发标记,减少Full GC风险但增加GC频率;设高了节省GC开销但Full GC风险大。大数据作业对象分配速度快,IHOP调低更安全。

追问三:怎么分析GC日志?

用GCViewer或GCEasy(在线工具)导入GC日志文件,看三个关键指标:① GC频率——Minor GC每秒几次正常,Full GC每小时不超过1次;② 暂停时间——P99暂停时间不超过MaxGCPauseMillis的2倍;③ 吞吐量——GC时间占总时间的比例应该低于5%。

总结

GC收集器面试讲清楚三点:① 主流收集器的对比(CMS已淘汰、G1是当前最佳选择、ZGC是未来方向);② G1的工作方式(Region分区、Mixed GC优先回收垃圾最多的Region、可设置暂停时间目标);③ 大数据场景的GC调优参数(MaxGCPauseMillis、IHOP、G1HeapRegionSize)。能讲出CMS Concurrent Mode Failure导致Executor被kill的踩坑经历和改G1后解决的过程,面试官会非常满意。

下一篇聊一个Java基础但面试必考的题:HashMap为什么线程不安全?ConcurrentHashMap怎么实现的?

你们大数据组件用的什么GC收集器?调过哪些参数?评论区聊聊~

关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长

刷题进度保存在当前浏览器