本地Docker环境Spark Driver与Executor内存计算及OOM问题处理
解决PySpark单机Docker环境下Java堆内存溢出问题
一、是否需要调整内存参数?
完全有必要。Spark默认的Driver和Executor内存分配(均为1GB左右)远远不足以处理Parquet文件读取场景——从报错堆栈来看,问题出在Parquet读取RowGroup时无法分配足够的ByteBuffer,本质就是堆内存不足。
在**非集群(本地模式)**下,Spark的Executor是运行在本地进程中的,调整--driver-memory和--executor-memory参数完全有效,能直接缓解内存压力。
二、基于你的硬件配置计算内存分配
你的机器是8核CPU、30GB内存,首先要给Docker容器分配合理的内存上限(建议留8-10GB给宿主机系统运行其他程序),比如给容器分配20GB内存。在此基础上拆分内存:
Driver内存(--driver-memory)
Driver负责任务调度,若你的脚本有collect()、show()这类将数据拉回Driver的操作,需预留足够内存。建议分配4-8GB,比如6g——既满足调度需求,也能处理少量数据回传。Executor内存与核数
本地模式下,Executor数量建议和CPU核数匹配,但要避免单个Executor内存过小或过大:- 总Executor可用内存 = 容器总内存 - Driver内存 - 预留内存(2GB,给Spark内部进程和容器系统)
- 按容器20GB计算:20GB - 6GB - 2GB = 12GB
- 8核CPU可拆分为4个Executor,每个分配2核、3GB内存(
--executor-cores 2、--executor-memory 3g),这样每个Executor有足够内存处理Parquet的RowGroup,同时不会浪费CPU资源。
三、修改后的提交命令
将内存参数添加到spark-submit命令中:
docker exec -it pyspark_container \ /usr/local/lib/python3.10/dist-packages/pyspark/bin/spark-submit \ --driver-memory 6g \ --executor-memory 3g \ --executor-cores 2 \ /spark_files/mapping.py;
四、额外优化建议
- 检查Parquet文件的RowGroup大小:若RowGroup超过256MB,写入时调整为128-256MB,减少单次读取的内存占用。
- 避免大量数据回传:尽量用Spark分布式API处理数据,少用
collect()这类将全量数据拉到Driver的操作。 - 调整分区数:读取Parquet后通过
repartition(n)增加分区,让每个分区的数据量更小,降低单个Executor的内存负载。
内容的提问来源于stack exchange,提问作者Tadeo
相关产品推荐
相关产品推荐

