一、发生oom的解决方案
一、Driver 内存不够
1、读取数据太大
-、增加Driver内存,–driver-memory
2、数据回传
-、collect会造成大量数据回传Driver,使用foreach
二、Executor 内存不够
1、map 类操作产生大量数据,包括 map、flatMap、filter、mapPartitions等
-、使用repartition,减少每个 task 计算数据的大小,从而减少每个 task 的输出 -、减少中间输出:用 mapPartitions 替代多个 map,减少 Executor 内存压力 -、数据跨节点移动是非常影响性能的,网络传输耗时,多次传输消耗内存,broadcast 在某些场景可以减少数据移动 -、使用谓词下推方式,filter 之后再 join -、使用cache and persist,缓存 RDD 既可以节省内存,也可以提高性能 -、避免使用groupByKey这种非combine的操作,尽量使用reduceByKey这种有combine的操作
2、shuffle 后产生数据倾斜
-、join时倾斜使用map端join 或 加盐处理 -、聚合操作倾斜使用两阶段聚合 -、shuffle量大时,调整–conf spark.memory.fraction(默认0.6)
3、coalesce调用导致内存溢出
coalesce操作是窄依赖,reduce阶段的task数量会缩小到对应map端操作的几倍,例如10倍 为避免从头到尾都是10个task执行,可以用repartition替换(有shuffle操作),或直接增加source端的并行数
4、RDD中大量对象容易导致OOM
-、RDD中存在大量的重复数据,或者Array中需要存储大量重复数据,可以将重复数据转化为String,能有效减少内存使用 因为字符串不管多少个,都只有一个String对象,指向常量池 算子内操作尽量能用基本数据类型就不用引用类型,能用数组就不用集合,另外还比如字符串拼接, 用StringBuffer代替+连接等等。这些方式不但可以节省空间还能增加算子的执行效率
5、shuffle reduce端缓冲大小以避免OOM
-、map端会实时将数据写入buffer中,reduce端从buffer中一边拉取一遍计算,reduce每次默认拉取最大值是48M, 但当上游数据量大时,reduce每次拉取数据全部达到自己缓冲最大极限时就会发生OOM,此时需要减少每次拉取 数据量,spark.reducer.maxSizeInFlight=48改为spark.reducer.maxSizeInFlight=24 减少reduce端task缓冲的大小, 宁愿每次少拉取一点,多拉取几次,不过这样性能会下降
三、参考文章
spark调优篇-oom 优化(汇总) Spark数据倾斜问题解决以及造成的spark OOM问题 Spark OOM解决办法 Spark之OOM解决方案 spark executor出现OOM内存溢出问题解决方案 spark之OOM常见问题梳理(一)
二、spark GC问题
参考文章
GC调优在Spark应用中的实践(转载)
|