Spark内存资源分配——spark.executor.memory等参数的设置方法

概述

基于论坛上一些关于spark内存设置的文章,我对一个项目中实际运行的任务进行了内存参数分析和优化。如果要了解更多详细设置原理,可见文末的参考文章链接。
已知内存分配存在通过用户提交的参数设置进行静态分配,和yarn进行动态分配两种,所以本文对两种状况都根据实际场景进行了分析。

资源详情

配置spark的内存参数,首先要基于集群资源的情况。本例的机器情况:一共8台机器,即8个Node。核心数:32 core / node;内存资源:50.8GB RAM/ node。
每个Node在计算的时候,给操作系统和Hadoop的进程预留2core,2.8GB,所以每个节点剩下28个core和48GB内存。

任务A——推断动态分配内存的过程

发现任务提交的参数设置为:
executor-memory=8g;num-executors=10;executor-cores=3。考虑到有MemoryOverhead,发现任务有参数将其设置为1G。(默认值是max(384M, 0.07 × spark.executor.memory))
因此按参数配置,本任务占用总内存为(8+1)10=90gb;核心数为310=30。可见一定没有占满,那么系统会基于memory动态分配core和executor-num。

executor个数:num-executors

因为一个executor其实可以跨node运行,因此用总可用内存数除以每个executor的内存数,可得总计num-executors=320/8=40,考虑有可能有1GB的MemoryOverhead,则num-executors应为320/9≈36,所以系统可能会动态分配36~40个executor。
也可能Yarn比我们设想的还要狠,给其他应用预留的空间更少,那么极限情况下把所有可用内存都给这个应用,那么最大的num-executors=(50.88)/8≈50,考虑MemoryOverhead,则num-executors应为(50.88)/9≈45。
最终,可以猜测Yarn动态分配的Executor个数在36~50个之间,40左右较为合理。
通过查看web页面的某个stage的执行计划,可以发现确实是40个executor。
Yarn中某个Stage的Executor分配情况

core的个数

本参数决定一个executor能够并发任务的个数。所以通常认为,一个executor越多的并发任务能够得到更好的性能。但有研究显示一个应用并发任务超过5,导致更差的性能。
目前已知共有40个executor,8个node,则一个Node平均5个executor。同时一个Node30个核(去掉预留的2个),那么如果动态分配,可能最多给每个Executor动态分配30/5=6个Core。
从Yarn的总Core分配界面可以看到差不多是这样。当然,如果有更好的方法从WEB界面的Spark ApplicationMaster里查看到core的数量,欢迎分享。
Yarn的Node详情

driver-memory大小

driver运行内存,默认值512m,一般2-6G。目前来看该参数对任务运行没有太大的影响,本案例中的设置值为4g。即,driver-memory=4g

————后来实际运行任务时,查看执行日志可以发现,这个任务总在报内存不足的错误,因此考虑设置合理的静态内存分配参数,把executor的内存调大,这就可以参考下面一个任务的设置过程。
修改之后,Yarn上的资源分配情况,可以看出确实和新设置的参数很符合,即1个Executor占20G内存。在这里插入图片描述

任务B——静态分配内存参数的设置过程

因为该任务经常报超内存的错误,所以先设置memory大小。

memory大小

配置每个executor的内存,一个node,48G内存可用。考虑到集群还会有其他任务运行,所以给其他任务留8GB,所以设置每个 executor可配置内存为40GB。这也意味着一个node1个executor。
从Spark的内存模型角度,Executor占用的内存分为两部分:ExecutorMemory和MemoryOverhead,预留出MemoryOverhead的内存量之后,才是ExecutorMemory的内存。
MemoryOverhead的计算公式: max(384M, 0.07 × spark.executor.memory)
因此 MemoryOverhead = 0.07 × 40G = 2.8G=2867MB 约等于3G > 384M
最终executor的内存配置值为 40G – 3 =37 GB
因此设置:executor-memory = 37 GB;spark.executor.memoryOverhead=3*1024=3072

core的个数

决定一个executor能够并发任务的个数。所以通常认为,一个executor越多的并发任务能够得到更好的性能。在本次设置中,理论上来说,由于1个node只有1个executor,所以可以用24个core。但有研究显示一个应用并发任务超过5,导致更差的性能。
所以core的个数暂设置为5个。
5个core是表明executor并发任务的能力,并不是说一个系统有多少个core,即使我们一个CPU有32个core,也设置5个core不变。
因此设置:executor-cores=5

executor个数

因为已经设置好1个node只有1个executor,所以,之后通过每个node的executor个数,可以得到整个任务可以分配的executors个数。
我们有8个节点,每个节点1个executor,8 × 1 = 8个executors,额外预留1个executor给AM,最终要配置7个executors。
因此设置:num-executors=7

driver-memory大小

driver运行内存,默认值512m,一般2-6G。目前来看该参数对任务运行没有太大的影响,因此就设置4g。
因此设置:driver-memory=4g

参考文章

对参数设置讲的很细的一篇,本文重点参考:Spark任务的core,executor,memory资源配置方法

对Spark Executor Memory做系统讲解,特别是讲到内存分为执行内存和存储内存两部分。还介绍了一些别的参数:如何设置Spark Executor Memory的大小

延申的内存调优,即对shuffle过程的参数调优,这个本例没有用到,有兴趣的话可以尝试一下:Spark学习(五)Spark Shuffle及内存分配

### 设置 Spark YARN Executor MemoryOverhead 参数Spark 中,`spark.yarn.executor.memoryOverhead` 参数用于指定每个执行器所需的额外内存(堆外内存),这部分内存不被 JVM 控制,主要用于 shuffle 数据传输和其他非堆内存需求[^4]。如果需要将该参数设置为 2048 MB,则可以按照以下方法操作: #### 方法一:通过 `spark-submit` 命令设置 可以在提交 Spark 应用程序时,使用 `--conf` 参数直接设置 `spark.yarn.executor.memoryOverhead` 的值: ```bash spark-submit --conf spark.yarn.executor.memoryOverhead=2048 ... ``` 上述命令会将 YARN 执行器的内存开销设置为 2048 MB。 --- #### 方法二:修改 `spark-defaults.conf` 配置文件 也可以在集群的全局配置文件 `spark-defaults.conf` 中添加或更新如下配置项: ```properties spark.yarn.executor.memoryOverhead 2048 ``` 这样每次运行基于此配置文件的应用都会自动应用这一设置。 --- #### 方法三:在代码中动态设置 如果希望在应用程序内部动态调整该参数,可以通过创建 `SparkConf` 对象并将其传递给 `SparkSession` 来实现: ```scala val conf = new SparkConf() .setAppName("MyApp") .set("spark.yarn.executor.memoryOverhead", "2048") val spark = SparkSession.builder().config(conf).getOrCreate() ``` 需要注意的是,从 Spark 2.3 版本开始,参数名称已更改为 `spark.executor.memoryOverhead`[^3]。因此,在较新的 Spark 版本中应改用以下代码片段: ```scala .set("spark.executor.memoryOverhead", "2048") ``` --- #### 注意事项 1. 如果正在使用低于 Spark 2.3 的版本,则需继续沿用旧版参数名 `spark.yarn.executor.memoryOverhead`[^2]。 2. 当遇到诸如 `java.lang.OutOfMemoryError: Direct buffer memory` 报错时,可能需要进一步调整与 JVM 直接缓冲区相关的选项 `spark.executor.extraJavaOptions -XX:MaxDirectMemorySize`。 3. 在某些情况下,`spark.executor.memoryOverhead` 还包含了 Tungsten 项目的堆外内存部分 (`spark.memory.offHeap.size`),这取决于具体的 Spark 版本及其行为特性。 --- ### 总结 无论采用哪种方式,都可以成功将 Spark YARN 执行器的内存开销参数设置为 2048 MB。具体选择哪一种方法取决于实际场景以及团队的工作流习惯。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值