记录:ERROR YarnScheduler: Lost executor 2 on XXX: Container killed by YARN for exceeding memory limits

问题描述

最近在pyspark处理90多G数据的时候,遇到这个问题,特此记录,希望能够帮到你

首先你可能会有以下错误或警告:

Lost executor 2 on bjxg-bd-slave65: Container killed by YARN for exceeding memory limits. 
 60.1 GB of 55 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead 
 or disabling yarn.nodemanager.vmem-check-enabled because of YARN-4714

在这里插入图片描述
或者在执行行动算子的时候遇到这种问题:

在这里插入图片描述

在web UI你会看到,stage里有好多failed

在这里插入图片描述

解决办法

1. 确保不是数据倾斜

如果你用了groupby这样的分组聚合操作,数据量大了之后可能就会发生数据倾斜,导致某几个task的数据量特别大,超出分配的内存被kill,像这种情况只能是优化算子,比如两端聚合的方式解决,具体看:

https://blog.csdn.net/qq_42363032/article/details/119824492

2. 利用cache,算子调优

  • 其次要确保你的惰性算子没有被重复的执行,利用cache或者persist,在行动算子之前进行缓存,当然也可以设置存储级别,详细的可自行百度
  • 关于spark算子调优也是一堆,我只说我解决这个错误所用到的:
    • 1.广播大变量broadcast,用完之后记得手动GC unpersist
    • 2.尽量少用count、collect这种拉取到driver端的行动算子,可以在它俩之前加cache,用后upersist。为什么要之前加cache?因为spark惰性计算。
    • 3.尽量避免大表join小表的shuffle操作,如果实在避免不了可以利用广播,这个也是一百度一大堆
    • 4.在处理的时候,能通过select或filter减少shuffle的数据一定要提前减少,降低处理时内存占用和通信时间
    • 5.确保你处理的数据是没有null的,我试过,如果有null的话,明显要比没有null的快,就算你填个空串也比null强

3. 资源调优

大家可以百度到,这种报错,很多都说加executor memory和executor memoryOverhead,加这个是没错,但是要确保你的整个处理流程,算子是想不到哪里还可以优化了,然后再加资源,这才是正确的调优逻辑。先分享我的资源:

ss = SparkSession(sc).builder \
    .config('spark.sql.shuffle.partitions', 3000) \
    .config('spark.driver.memoryOverhead', '30g') \
    .config('spark.driver.maxResultSize', '30g') \
    .config('spark.executor.memoryOverhead', '40g') \
    .config('spark.shuffle.io.maxRetries', 10) \
    .config('spark.shuffle.io.retryWait', 10) \
    .config('spark.default.parallelism', 30) \
    .config('spark.kryoserializer.buffer.max', 5120) \
    .config('spark.dynamicAllocation.enabled', 'true') \
    .config("spark.sql.execution.arrow.enabled", "true")\
    .config("spark.memory.fraction", 0.2)\
    .config('spark.sql.caseSensitive', 'true') \
    .getOrCreate()
PYSPARK_PYTHON=/data/anaconda3/bin/python3 \
  /opt/spark/bin/spark-submit \
      --master yarn \
      --deploy-mode client \
      --driver-memory 30g \
      --driver-cores 4 \
      --executor-memory 50g \
      --num-executors 6 \
      --executor-cores 5 \
  • driver-memorydriver-cores:字面意思driver的内存和核数,这个根据数据量和处理复杂度进行设置
  • executor-memorynum-executorsexecutor-cores:分别为executor的内存、数量、核数,也是根据要处理的数据量和复杂度进行设置,我这两相当于给了50 * 6的内存,6*5的核数相当于我rdd并行度最高是30,记得看到过一篇文章说executor-cores最好不要超过6,最好的是num-executors多一点
  • spark.sql.shuffle.partitions:spark sql的并行度,对于大数据来说高点还是有用的,能够轻微的防止数据倾斜,但是小数据的并行度尽量别太高,要不然跑的太慢,默认是200
  • spark.driver.memoryOverhead:driver的堆外内存
  • spark.driver.maxResultSize:它是所有分区序列化结果大小的总和,它不能大于你的executor-memory,在范围内增大可以防止内存不足
  • spark.executor.memoryOverhead:executor的堆外内存,我理解的它是executor所需的额外内存开销
  • spark.default.parallelism:rdd的并行度,它是你executor数量和核数的乘数,比如我这就是5*10
  • spark.memory.fraction:这个值一定要调,它默认是0.6,也就是40%的空间保留你的数据结构,元数据等,调到0.2,说明你有80%的空间保留你的这些数据。它可以在你cache的时候,先在磁盘,在再内存,相当于减少了缓存时用的内存。



如果帮到你,请你点赞支持

猜你喜欢

转载自blog.csdn.net/qq_42363032/article/details/123730750
今日推荐