一、常见问题
1、org.apache.spark.shuffle.FetchFailedException
当前的配置为每个 executor 使用 1cpu,5GRAM,启动了 20 个 executor,
这种问题一般发生在有大量 shuffle 操作的时候,task 不断的 failed,然后又重执行,一直循环下去,非常的耗时。
解决方案:
一般遇到这种问题提高 executor 内存即可,同时增加每个 executor 的 cpu,这样不会减少task 并行度。
spark.executor.memory 15G
spark.executor.cores 3
spark.cores.max 21
2、倾斜问题:
大多数任务都完成了,还有那么一两个任务怎么都跑不完或者跑的很慢。
分为数据倾斜和 task 倾斜两种。
数据倾斜:
数据倾斜大多数情况是由于大量 null 值或者""引起,在计算前过滤掉这些数据既可。
例如:sqlContext.sql("...where col is not null and col != ''")
任务倾斜:
task 倾斜原因比较多,网络 io,cpu,mem 都有可能造成这个节点上的任务执行缓慢,可以去看该节点的性能监控分析原因。
或者可以开启 spark 的推测机制,开启推测机制后如果某一台机器的几个 task 特别慢,推测机制会将任务分配到其他机器执行,最后 Spark 会选取最快的作为最终结果
spark.speculation true
spark.speculation.interval 100 - 检测周期,单位毫秒;
spark.speculation.quantile 0.75 - 完成 task 的百分比时启动推测
spark.speculation.multiplier 1.5 - 比其他的慢多少倍时启动推测。
3、内存溢出。
内存不够,数据太多就会抛出 OOM 的 Exeception。
增加 executor 内存总量,也就是说增加 spark.executor.memory 的值
增加任务并行度(大任务就被分成小任务了),参考下面优化并行度的方法
二、优化
1、内存分配方面
如果执行的任务shuffle量特别大,rdd缓存的数据比较少,可以减少分配给rdd缓存的比例和增大分配给shuffle数据的内存比例。
spark.storage.memoryFraction spark.shuffle.memoryFraction |
内存空间不足:
如果任务运行缓慢, jvm 进行频繁 gc 或者内存空间不足,可以降低上述的两个值。
"spark.rdd.compress","true" - 默认为 false,压缩序列化的 RDD 分区,消耗一些cpu 减少空间的使用
如果数据只使用一次,不要采用 cache 操作,因为并不会提高运行速度,还会造成内存浪费。
2、并行度,即数据分片
spark.default.parallelism 发生 shuffle 时的并行度
数量设置太大会造成很多小任务,增加启动任务的开销,太小,内存压力大,运行大量数据的任务时速度缓慢。
spark.sql.shuffle.partitions sql 聚合操作(发生 shuffle)时的并行度,默认为 200,如果任务运行缓慢增加这个值
修改 map 阶段并行度主要是在代码中使用 rdd.repartition(partitionNum)来操作。