FAQ-GC overhead limit exceeded 错误解决思路

问题描述/异常栈
当使用 Spark SQL 时遇到 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误,这通常意味着 JVM 在进行垃圾回收时,耗费了过多的时间和内存,导致可用内存不足。这是一个表明内存使用效率低下的警告,通常会导致程序失败。以下是一些可能的解决方法和优化建议
解决方案
1. 增加内存配置

根据实际情况增加 Executor 和 Driver 的内存

--conf spark.executor.memory=4g

--conf spark.driver.memory=2g

增加 JVM 的内存开销

--conf spark.yarn.executor.memoryOverhead=512m

2. 调整 GC 策略

使用 G1 垃圾回收器 G1 GC 通常更适合大内存和大数据集:

--conf "spark.executor.extraJavaOptions=-XX:+UseG1GC"

调整 GC 相关参数 你可以尝试调整一些 JVM 的 GC 选项,例如:

-XX:GCTimeRatio=19

-XX:MaxGCPauseMillis=100

3. 优化数据处理

优化数据结构 减少数据集的大小,例如通过选择必要的列和行,避免加载不必要的数据。 使用高效的数据格式 使用 Parquet 或 ORC 格式,这些格式在 Spark 中性能更好且压缩更有效。

4. 增加并行度

调整并行度 spark.default.parallelism

--conf spark.default.parallelism=100

5. 监控和分析

使用 Spark UI 观察 监控 Spark UI,查看哪个阶段的内存使用情况高,识别潜在的内存泄漏。 分析作业的执行 检查作业的执行计划,确认是否有不必要的 Shuffle 操作。

6. 增加 GC Overhead Limit

调整 GC overhead limit

-XX:-UseGCOverheadLimit

7. 代码优化

避免大对象和集合 通过采取上述措施,你应该能够减少或消除 GC overhead limit exceeded 错误,提高 Spark SQL 的性能和稳定性。如果问题依旧存在,可以考虑进一步分析应用逻辑和数据处理流程。

8. 总结

目前发现该问题的现场情况是用户sql逻辑复杂,存在特别多case when 等语句,暂时通过增加内存和调整GC策略,使任务成功运行;但建议还是优先进行代码逻辑优化;

问题原因
JVM 在进行垃圾回收时,耗费了过多的时间和内存,导致可用内存不足

作者:李云龙