分析
spark常见的问题不外乎oom:
我们首先看一下Spark 的内存模型:
Spark在一个Executor中的内存分为三块,一块是execution内存,一块是storage内存,一块是other内存。
execution内存是执行内存,文档中说join,aggregate都在这部分内存中执行,shuffle的数据也会先缓存在这个内存中,满了再写入磁盘,能够减少IO。其实map过程也是在这个内存中执行的。
storage内存是存储broadcast,cache,persist数据的地方。
other内存是程序执行时预留给自己的内存。
OOM的问题通常出现在execution这块内存中,因为storage这块内存在存放数据满了之后,会直接丢弃内存中旧的数据,对性能有影响但是不会有OOM的问题。
Spark中的OOM问题不外乎以下三种情况
map执行中内存溢出
shuffle后内存溢出
driver内存溢出
前两种情况发生在executor中,最后情况发生在driver中
我们针对每种情况具体分析
Driver heap:
Driver heap OOM的三大原因:
(1).用户在Driver端口生成大对象, 比如创建了一个大的集合数据结构
解决思路:
1.1. 考虑将该大对象转化成Executor端加载. 例如调用sc.textFile/sc.hadoopFile等
1.2. 如若无法避免, 自我评估该大对象占用的内存, 相应增加driver-memory的值
(2).从Executor端收集数据回Driver端
比如Collect. 某个Stage中Executor端发回的所有数据量不能超过spark.driver.maxResultSize,默认1g. 如果用户增加该值, 请对应增加2delta increase到Driver Memory, resultSize该值只是数据序列化之后的Size, 如果是Collect的操作会将这些数据反序列化收集, 此时真正所需内存需要膨胀2-5倍, 甚至10倍.
解决思路:
2.1. 本身不建议将大的数据从Executor端, collect回来. 建议将Driver端对collect回来的数据所做的操作, 转化成Executor端RDD操作.
2.2. 如若无法避免, 自我评collect需要的内存, 相应增加driver