好的,我们来详细探讨 Spark 性能调优中的最优资源配置。这是提升 Spark 作业执行效率的基础,需要根据集群资源和作业需求进行精细调整。
Spark 性能调优的第一步,就是为任务分配更多的资源,在一定范围内,增加资源的分配与性能的提升是成正比的,实现了最优的资源配置后,在此基础上再考虑进行后面论述的性能调优策略。
🧠 核心思路
资源配置的目标是最大化集群资源的利用率,避免资源浪费(如 CPU 空闲)或资源瓶颈(如内存不足导致频繁 GC 或 OOM)。主要关注点包括:
资源总量分配:为 Spark 应用程序分配多少集群资源。资源内部划分:如何将这些资源划分给 、
Driver 以及每个
Executor 内部的
Executor 和
Core。动态分配:是否启用资源动态伸缩以适应作业不同阶段的需求。
Memory
📌 1. 资源总量分配 (YARN 模式为例)
在 YARN 集群上提交 Spark 作业时,需指定应用程序可使用的资源上限:
spark-submit
--master yarn
--deploy-mode cluster
--num-executors 10 # 初始 Executor 数量
--executor-cores 4 # 每个 Executor 的 CPU 核数
--executor-memory 16G # 每个 Executor 的内存大小
--driver-memory 4G # Driver 内存
--total-executor-cores 40 # 总 CPU 核数上限 (可选)
: 初始请求的
--num-executors 数量。并非越多越好,需考虑集群总资源和任务并行度。
Executor: 每个
--executor-cores 可同时运行的
Executor 数。通常建议在
Task 之间,避免过少(CPU 空闲)或过多(内存竞争、GC 压力)。
4-8: 每个
--executor-memory 的堆内存。需预留部分内存给堆外内存(Off-Heap Memory)和操作系统。
Executor:
--driver-memory 内存,用于存储任务状态、广播变量等。对于涉及大量数据聚合或宽依赖的作业,需要较大内存。
Driver
⚙️ 2. Executor 资源配置优化
(1) 内存分配比例
每个 的内存 (
Executor) 由以下几部分组成:
--executor-memory
: 堆外内存(如 JVM 自身、线程栈、NIO Buffer)。默认是
spark.executor.memoryOverhead 的
executor-memory (最小
10%)。
384M
公式:
实际总内存=–executor-memory+max(384M,0.1×–executor-memory)” role=”presentation”>实际总内存=–executor-memory+max(384M,0.1×–executor-memory)实际总内存=–executor-memory+max(384M,0.1×–executor-memory)
堆内内存 (): 由 Spark 管理,进一步划分为:
spark.executor.memory
: 统一内存池比例(默认
spark.memory.fraction),用于执行内存(Shuffle、Join、Sort)和存储内存(Cache)。
0.6: 存储内存占统一内存池的比例(默认
spark.memory.storageFraction),可被执行内存借用。
0.5
优化建议:
若观察到频繁的 OOM (堆内或堆外),考虑增加
Executor 或调整
--executor-memory。若
memoryOverhead 时间过长,可能是堆内内存不足或对象过多,可尝试增大堆内存或优化数据结构。
GC
(2) CPU 核数与并行度
: 默认并行度(RDD Partition 数),通常建议设置为
spark.default.parallelism 左右。Executor 核心数:每个
(集群总核心数) * 2 的
Executor 数 (
Core) 决定了其并发执行
--executor-cores 的能力。
Task
理想情况:每个 处理
Core 个活跃
1,同时有少量
Task 等待(避免空闲)。
Task
总并行度 ≈ 。
num-executors * executor-cores
🔄 3. 动态资源分配
Spark 支持在作业运行时动态增减 :
Executor
spark-submit
--conf spark.dynamicAllocation.enabled=true
--conf spark.dynamicAllocation.initialExecutors=5
--conf spark.dynamicAllocation.minExecutors=2
--conf spark.dynamicAllocation.maxExecutors=20
优点:适应任务负载变化,提高集群利用率。缺点: 启动/销毁有开销,可能影响短作业性能。
Executor
📊 4. 监控与调优验证
Spark Web UI: 查看各 的
Executor 时间、
GC 读写量、
Shuffle 执行时间分布。日志:关注
Task 是否因 OOM 被终止。工具:使用
Executor,
jstat 分析 JVM 内存和 GC。
jmap
🧪 示例:内存计算
假设集群节点配置为 核
32 内存,计划分配:
128G
--num-executors=15
--executor-cores=2
--executor-memory=8G
则:
总内存 ≈ ≈
15 * (8G + max(0.8G, 0.1*8G)) =
15 * 8.8G (接近节点内存)总 CPU 核数 =
132G =
15 * 2 (接近节点核心)
30
💎 总结
最优资源配置没有固定公式,需结合:
集群物理资源(CPU、内存、网络)。作业特性(数据量、计算复杂度、 量)。监控反馈(GC、OOM、CPU 利用率)。
Shuffle
通过多次测试和监控分析,逐步逼近最佳配置点。