spark内存溢出及其解决方案

1、你在工作当中有遇到内存溢出问题吗?你是如何解决的?

    回答思路:先解释spark的内存模型,再分情况介绍不同情况下的解决方案。总体思想是根据内存模型找出不够的那一块内存,要么提升占比,要么整体增加。


spark2.x的内存模型

oom通常出现在execution内存中,因为storage这块内存在放满之后,会直接丢弃内存中旧的数据,对性能有点影响但不会导致oom。存储内存和执行内存可以互相借用内存空间。

而spark的oom问题主要分为三种情况:

①map执行后的内存溢出

--场景:maptask所运行的executor内存溢出。

    增加堆内内存,申请的堆外内存也会随之增加

    --executor -memory 

    增加堆外内存

    --conf spark.excutor.memoryoverhead 2048

    默认申请的堆外内存是Executor内存的10%。

②shuffle后内存溢出

    reduce task去map一边拉取数据,一边聚合。reduce端有一块聚合内存,executor memory *0.2

    解决方案:增加reduce聚合内存的比例,设置spark.shuffle.memoryfraction

    增加executor memory的大小

    减少reduce task每次拉取的数据量,设置spark.reducer.maxSizeInFlight 24m

③driver内存溢出

    --场景一:用户在Dirver端口生成大对象,比如创建了一个大的集合数据结构

    解决思路:Ⅰ将大对象转换成Executor端加载,比如调用sc.textfile

                       Ⅱ评估大对象占用的内存,增加dirver-menory的值

    --场景二:从Executor端收集数据(collect)回Dirver端

    解决思路:Ⅰ本身不建议将大的数据从executor端,collect回来。建议将driver端对collect回来的数据所作的操作,转换成executor端rdd操作

                       Ⅱ若无法避免,估算collect需要的内存,相应增加driver-memory的值

    --场景三:spark自身框架的消耗

    主要由spark UI数据消耗,取决于作业的累计task个数

    解决思路:Ⅰ从hdfs load的parition是自动计算,但在过滤之后,已经大大减少了数据量,此时可以缩小partitions。

                      Ⅱ通过参数spark.ui.retainedStages/spark.ui.retainedjobs控制(默认1000)

2、shuffle file not found可能是什么原因导致的报错?

    产生该报错的原因可能是后一个stage的task从上一个stage的task所在的executor拉取数据,但是上一个stage正在执行GC,导致数据没有拉渠道,出现该错误。可以通过调整拉取的次数和间隔时间来避免此类事件发生。

val conf =new SparkConf()

    .set("spark.shuffle.io.maxRetries","6')

    .set("spark.shuffle.io.retrywait","60s")

3、栈溢出?

    yarn-client模式下,Dirver是运行在本地机器上的,spark使用的jvm的permGen是128m,可能在client上测试没有问题

    yarn-cluster模式下,Dirver是运行在集群的某个节点上,使用的是没有经过配置的默认配置,PermGen永久代大小为82m。运行时报栈溢出。

    --解决方案:在spark-submit脚本中对相关参数进行设置

    --conf spark.dirver.extraJavaOptions="-xx:PerSize=128M -xx:MaxPermSize=256m"

你可能感兴趣的:(spark内存溢出及其解决方案)