Spark3 Executor物理内存超限:RSS内存构成及优化方案咨询
Spark 3 SQL作业YARN内存超限及RSS内存统计差异问题解决
问题描述
运行基于Spark 3的Spark SQL作业,配置如下:
set spark.executor.memory=8G; set spark.executor.cores=3; set spark.yarn.executor.memoryOverhead=3072;
作业未启用堆外内存,但执行时触发YARN内存超限错误:
Container killed by YARN for exceeding physical memory limits. 12.1 GB of 11 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead。
开启Executor RSS报告后,发现RSS内存总量不等于堆内内存、堆外内存、direct-pool memory、mapped-pool memory的总和,需明确原因、未统计的内存组件及解决办法。
一、RSS内存与统计组件总和不匹配的原因
RSS(驻留集大小)是进程实际占用的物理内存总量,Spark的内存报告仅统计了JVM层面的核心内存区域,以下是未被统计的内存占用组件:
- JVM基础开销:包括线程栈内存(每个线程默认1MB,3核配置下Spark默认对应6个线程,至少占用6MB)、元空间(Metaspace,存储类元数据,依赖类库较多时占用显著)、垃圾回收器专属内存(如GC标记缓冲区、线程本地缓存等)。
- Native库内存:Spark依赖的原生压缩库(snappy/lz4)、序列化库(Kryo原生部分)、HDFS客户端原生代码等,这部分内存脱离JVM管控,不会被Spark统计。
- 系统级进程开销:操作系统为进程分配的页表、文件描述符、信号处理内存,以及进程加载的共享系统库(如libc、libjvm.so)占用的内存。
- 第三方依赖内存:作业引入的自定义Jar包中,若存在JNI调用、直接调用系统API分配的内存,也不会被Spark内存报告统计。
二、解决YARN内存超限的具体方案
调整内存预留值
当前spark.yarn.executor.memoryOverhead=3072(3GB)+堆内8GB=11GB,远低于实际占用的12.1GB,建议先将overhead调整为4GB(4096),若仍超限可提升至堆内内存的40%-50%:set spark.yarn.executor.memoryOverhead=4096;限制JVM元空间大小
显式设置元空间的初始值和最大值,避免其无限制增长:set spark.executor.extraJavaOptions=-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1024m;优化线程配置降低栈内存
减少单executor的核心数,降低线程总数(每个线程默认1MB栈内存),同时增加executor实例数保证并行度:set spark.executor.cores=2; set spark.executor.instances=15; -- 根据集群资源调整实际数值排查依赖与原生库
- 清理作业中不必要的第三方Jar包,排查是否存在内存泄漏的依赖;
- 若排查原生库占用,可临时改用纯Java实现的压缩库(如gzip),验证是否是原生库导致的内存超限(注意:此操作会影响性能,仅作排查用)。
补充内存监控定位问题
- 添加JVM监控参数,查看GC和元空间的内存变化:
set spark.executor.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintMetaspaceStatistics; - 用操作系统工具(如
top、pmap)直接查看executor进程的内存分布,定位未被Spark统计的内存占用区域。
- 添加JVM监控参数,查看GC和元空间的内存变化:
内容的提问来源于stack exchange,提问作者nan nan
相关产品推荐
相关产品推荐

