Spark Executor 内存分配原理
在 Apache Spark 中,Executor 是运行任务的基本单元,它负责数据存储和任务执行。Executor 的内存分配是影响性能的重要因素,主要由以下几个区域组成:
1. Executor 内存布局
Spark Executor 的内存结构可以分为以下部分:
- 堆内存(On-heap Memory):
- Execution Memory(执行内存): 用于存储临时数据,例如 shuffle 操作的中间结果和 join 时的临时数据。
- Storage Memory(存储内存): 用于缓存 RDD 数据或广播变量。
- User Memory(用户内存): 用于用户自定义数据结构。
- 堆外内存(Off-heap Memory):
- 在 Spark 2.x 及以后支持,通过
spark.memory.offHeap.enabled
启用,用于存储外部数据,例如 Tungsten 内存管理。
- 在 Spark 2.x 及以后支持,通过
- 其他内存:
- 元数据和 JIT 编译消耗的 JVM 内存。
- 内部线程和任务分配的内存。
2. Executor 内存分配计算
- Executor Memory 总大小由参数
spark.executor.memory
控制。 - 内部划分的比例由
spark.memory.fraction
和spark.memory.storageFraction
确定:spark.memory.fraction
:分配给 Execution 和 Storage 的内存占总 Executor 内存的比例,默认值为0.6
。spark.memory.storageFraction
:Storage 内存在 Execution + Storage 内存中的比例,默认值为0.5
。
公式:
- 可用堆内存:复制代码
可用堆内存 = spark.executor.memory × spark.memory.fraction
2. Storage Memory 和 Execution Memory:
Storage Memory = 可用堆内存 × spark.memory.storageFraction
Execution Memory = 可用堆内存 × (1 - spark.memory.storageFraction)
Spark Executor 内存调优
优化 Spark Executor 的内存分配可以有效提高作业性能。以下是一些关键调优技巧:
1. 合理分配 Executor 内存
- 增大
spark.executor.memory
: 提升总内存,可以缓解任务因内存不足而失败。 - 设置合适的
spark.executor.cores
:- 每个 Executor 的核心数决定任务的并发数。
- 通常 1 核配 2GB 内存,避免因过多线程竞争导致性能下降。
2. 优化内存分配比例
- 调整
spark.memory.fraction
:- 如果作业以计算为主,增大
Execution Memory
,减小Storage Memory
。 - 如果作业需要大量缓存数据,增大
Storage Memory
。
- 如果作业以计算为主,增大
spark.memory.fraction = 0.7 # Execution 和 Storage 占总内存的 70%
spark.memory.storageFraction = 0.3 # Storage 占 Execution + Storage 的 30%
3. 使用堆外内存
- 启用堆外内存: 如果堆内存不足,可以启用堆外内存:
spark.memory.offHeap.enabled = true
spark.memory.offHeap.size = 4g
- 避免频繁的垃圾回收(GC)。
4. 数据分区与并行度
- 增加分区数以减少单个任务处理的数据量:
spark.sql.shuffle.partitions = 200 # 默认是 200,根据任务复杂度调整
5. 避免内存溢出
- 广播大表: 使用
broadcast
广播小表,减少 join 时中间结果占用内存。
from pyspark.sql.functions import broadcast
df = large_df.join(broadcast(small_df), "key")
- 缓存策略: 合理使用
.persist(StorageLevel.MEMORY_AND_DISK)
,防止内存溢出。
6. 调整 JVM 堆内存
- 增大
spark.executor.extraJavaOptions
:
spark.executor.extraJavaOptions = "-XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"
常见问题与解决
- 内存不足导致 OOM
- 增大
spark.executor.memory
或减少分区数据量。 - 检查是否有大量缓存数据并清理无用缓存。
- 增大
- 频繁 GC
- 启用堆外内存减少 JVM 压力。
- 使用
-XX:+UseG1GC
优化垃圾回收。
- Shuffle 操作导致内存瓶颈
- 增加
spark.sql.shuffle.partitions
。 - 优化数据分区策略,避免数据倾斜。
- 增加
通过以上调整,可以显著优化 Spark Executor 的内存使用,提高作业性能。
发布者:myrgd,转载请注明出处:https://www.object-c.cn/4482