关于spark在yarn上运行时候内存的介绍

在YARN上运行Spark时,内存管理是性能调优的核心环节。以下是 Driver MemoryExecutor Memory堆内存(Heap Memory)堆外内存(Off-Heap Memory) 的区别与配置方法,以及实际场景中的最佳实践:


1. 核心概念与区别

(1) Driver Memory
  • 角色 :Driver是Spark应用程序的主控进程,负责:
    • 解析用户代码,生成DAG(任务执行计划)。
    • 调度Task到Executor,并监控执行状态。
    • 收集结果(如collect()操作)或广播变量。
  • 内存组成
    • 堆内存:存储元数据(如Task定义、广播变量)和收集的结果数据。
    • 堆外内存:JVM自身开销、直接内存(如网络传输缓存)。
  • 关键参数
    • spark.driver.memory:Driver的堆内存(默认1g)。
    • spark.driver.memoryOverhead:Driver的堆外内存(默认max(384MB, 0.1 * spark.driver.memory))。
(2) Executor Memory
  • 角色 :Executor是工作节点上的任务执行进程,负责:
    • 执行具体的Task(如Map、Reduce操作)。
    • 缓存数据(如cache()persist())。
  • 内存组成
    • 堆内存:存储Task处理的数据、缓存的数据。
    • 堆外内存:Shuffle中间数据、原生操作(如HDFS读写缓存)。
  • 关键参数
    • spark.executor.memory:Executor的堆内存(默认1g)。
    • spark.executor.memoryOverhead:Executor的堆外内存(默认max(384MB, 0.1 * spark.executor.memory))。
    • spark.memory.fraction:Executor中用于计算和缓存的总内存占比(默认0.6)。
(3) 堆内存 vs 堆外内存
特性 堆内存(Heap) 堆外内存(Off-Heap)
管理方式 由JVM垃圾回收器(GC)管理 不受GC管理,需手动释放或依赖操作系统管理
存储内容 Java对象实例(如RDD数据、集合) JVM元数据、直接缓冲区(DirectByteBuffer)、Shuffle临时文件
溢出风险 OutOfMemoryError: Java heap space OutOfMemoryError: Direct buffer memory 或YARN/K8s容器被杀死
配置参数 spark.driver.memoryspark.executor.memory spark.driver.memoryOverheadspark.executor.memoryOverhead

2. 内存设置规则

(1) 总内存限制

在YARN集群中,Driver和Executor的内存需满足:

  • Driver总内存 ≤ YARN单容器内存上限(由yarn.scheduler.maximum-allocation-mb定义)。
  • Executor总内存 ≤ YARN单容器内存上限。

总内存计算公式:

plaintext 复制代码
Driver总内存 = spark.driver.memory + spark.driver.memoryOverhead
Executor总内存 = spark.executor.memory + spark.executor.memoryOverhead
(2) 配置建议
参数 Driver Executor 说明
堆内存 spark.driver.memory spark.executor.memory - Driver :根据收集数据量和广播变量大小调整。 - Executor:根据分区数据量和缓存需求调整。
堆外内存 spark.driver.memoryOverhead spark.executor.memoryOverhead - 默认值通常不足!若任务涉及大量Shuffle或Native操作,需手动增加。
内存分配比例 - spark.memory.fraction 调整Executor内计算内存(Execution)和缓存内存(Storage)的比例。
(3) 典型场景设置示例
  • 场景1:常规ETL任务

    bash 复制代码
    spark-submit \
      --driver-memory 4g \
      --executor-memory 8g \
      --conf spark.executor.memoryOverhead=2g \
      --conf spark.driver.memoryOverhead=1g \
      ...
    • 说明:Executor处理数据分区,预留2GB堆外内存应对Shuffle。
  • 场景2:需collect()大量数据

    bash 复制代码
    spark-submit \
      --driver-memory 16g \           # 收集10GB数据时,Driver堆内存需足够大
      --conf spark.driver.maxResultSize=10g \
      ...
    • 注意 :避免collect(),优先使用分布式写入(如write.parquet())。
  • 场景3:机器学习(频繁Shuffle)

    bash 复制代码
    spark-submit \
      --executor-memory 16g \
      --conf spark.executor.memoryOverhead=4g \  # Shuffle和原生库可能占用大量堆外内存
      --conf spark.memory.fraction=0.7 \         # 提高计算内存占比
      ...

3. 常见问题与调优

(1) Driver OOM(堆内存不足)
  • 表现java.lang.OutOfMemoryError: Java heap space
  • 解决方案
    • 增加spark.driver.memory
    • 避免在Driver中收集大数据(用take(n)替代collect())。
    • 减少广播变量大小。
(2) Executor OOM(堆内存不足)
  • 表现:Executor日志中抛出堆内存溢出。
  • 解决方案
    • 增加spark.executor.memory
    • 减少单个分区的数据量(通过repartition()增大分区数)。
    • 使用MEMORY_AND_DISK缓存级别。
(3) 容器被YARN杀死(堆外内存不足)
  • 表现 :YARN日志提示 Container killed due to exceeding memory limits
  • 解决方案
    • 增大spark.executor.memoryOverheadspark.driver.memoryOverhead
    • 检查是否使用Native库(如OpenBLAS)导致堆外内存泄漏。
(4) Shuffle阶段频繁溢写磁盘
  • 表现:Spark UI中Shuffle Write/Read量过大,任务变慢。
  • 解决方案
    • 增大spark.executor.memoryspark.memory.fraction(为Execution内存留更多空间)。
    • 优化数据倾斜(加盐、拆分倾斜Key)。

4. 最佳实践总结

配置项 推荐策略
Driver堆内存 根据collect()数据量设置,通常为数据量的2倍,不超过YARN容器上限。
Executor堆内存 根据分区数据量设置,建议8g~16g,避免单个Executor内存过大导致GC停顿。
堆外内存 至少为堆内存的20%~30%(如spark.executor.memoryOverhead=4g当Executor堆内存为16g)。
Shuffle优化 增大spark.sql.shuffle.partitions(默认200)到2-3倍数据分区数。
监控工具 使用Spark UI + YARN Web UI + Prometheus监控堆/堆外内存趋势。

5. 完整示例配置

bash 复制代码
spark-submit \
  --master yarn \
  --deploy-mode cluster \
  --driver-memory 8g \
  --executor-memory 16g \
  --conf spark.driver.memoryOverhead=2g \
  --conf spark.executor.memoryOverhead=4g \
  --conf spark.memory.fraction=0.7 \
  --conf spark.sql.shuffle.partitions=2000 \
  --conf spark.serializer=org.apache.spark.serializer.KryoSerializer \
  --class com.example.Main \
  /path/to/your-app.jar

通过合理分配堆内外内存、监控资源使用,并结合业务逻辑优化,可以显著减少Spark作业的OOM风险和性能瓶颈。

相关推荐
hf200012几秒前
技术深度报道:解析云器Lakehouse如何实现超越Spark 10倍性能提升
大数据·分布式·spark
快来卷java2 分钟前
RabbitMQ 技术详解:异步消息通信的核心原理与实践
java·分布式·rabbitmq
酷爱码1 小时前
zookeeper详细介绍以及使用
分布式·zookeeper·云原生
不辉放弃3 小时前
Flink/Kafka在python中的用处
大数据·python
薇晶晶4 小时前
虚拟机安装linux系统无法上网的解决方法
大数据
小钊(求职中)4 小时前
七种分布式ID生成方式详细介绍--Redis、雪花算法、号段模式以及美团Leaf 等
java·spring boot·分布式·spring·mybatis
martian6654 小时前
分布式并发控制实战手册:从Redis锁到ZK选主的架构之道
java·开发语言·redis·分布式·架构
阿里云大数据AI技术5 小时前
高效向量检索实践:阿里云百炼生成+Milvus存储技术方案解析
大数据·数据分析·云计算
小五Z5 小时前
RabbitMQ高级特性--重试特性
分布式·rabbitmq
小五Z5 小时前
RabbitMQ高级特性--TTL和死信队列
分布式·rabbitmq