一 控制reduce端缓冲区大小,避免OOM
buffer默认大小为48M
reduce端的task会一边拉取一边计算,不一定每次都会拉满48M
虽然增大reduce可以减少拉取次数,提高shuffle性能,但是map端数据量很大,写出的速度很快,reduce端在拉取的时候可能达到自己的缓冲的最大极限值(48M),再加上reduce执行聚合函数可能创建大量的对象,可能会导致内存溢出。
处理方式:此时应考虑减少reduce端拉取数据缓冲区的大小。
二 JVM GC导致shuffle文件拉取失败
错误:shuflle file not found
原因:下一个stage的task想去上一个stage的task所在的Executor拉取数据,结果对方正在执行GC,执行GC导致Executor内所有的工作线程全部暂停,导致没拉取到
处理方式:调整reduce拉取重试次数和拉取时间间隔,提高shuffle性能
val conf = new SparkConf().set("spark.shuffle.io.maxRetries","60").set("spark.shuffle.retryWait","60s")
三 解决各种序列化报错
报错信息中含有Serializable等词汇
1.作为RDD的元素类型的自定义类,必须是可以序列化的
2.算子函数里可以使用外部的自定义变量,必须是可以序列化的
3.不可以在RDD的元素类型、算子函数里使用第三方的不支持序列化的类型,比如Connection
四,解决算子函数返回NULL导致的问题
1.返回特殊值,不返回null,比如“-1”
2.在通过算子获取到了一个RDD之后,可以对这个RDD执行filter操作,进行数据过滤,将数值为-1的数据给过滤掉
3.在使用完filter算子后,继续调用colease算子进行优化
五,解决yarn-client模式导致网卡流量激增问题
![](https://i-blog.csdnimg.cn/blog_migrate/c559243a2fce49ad13a866ab3974c46a.png)
Driver启动在本地机器上,yarn-cluster模式不会出现此问题,由于一定是测试模式,Driver和Executor通信数据量很大,且频度高,网络通信增加。 需减少测试环境下的数据量
六 解决yarn-cluster模式的JVM栈内存溢出无法执行的问
题
yarn-client模式下,spark使用的jvm配置是本地机器上的spark-class文件,jvm永久代的大小是128M,但在yarn-cluster模式下,某个集群使用的没有经过配置的默认PerGen永久代大小为82M
此时如果PerGen的占用刚好大于82M,小于128M,就会在client可运行,cluster无法运行
解决方式:spark-submit脚本中设置参数
--conf spark.driver.extraJavaOptiona="-XX:PerGenSize=128M -XX:MaxPerSize=256M"
以此设置了Driver永久代大小,默认为128MB,最大256M
七 解决SpaekSQL导致的JVM栈内存溢出
当SparkSQL的sql与家具中有成百上千的or关键字,就可能出现Driver端的JVM栈内存溢出(递归)
解决:一条语句控制在100个or以内
八 持久化与checkpoint的使用
Spark持久化在大部分情况下是没有问题的,但是有时数据可能会丢失,如果数据一旦丢失,就需要对丢失的数据重新进行计算,计算完后再缓存和使用,为了避免数据的丢失,可以选择对这个RDD进行checkpoint,也就是将数据持久化一份到容错的文件系统上(比如HDFS)。
一个RDD缓存并checkpoint后,如果一旦发现缓存丢失,就会优先查看checkpoint数据存不存在,如果有,就会使用checkpoint数据,而不用重新计算。也即是说,checkpoint可以视为cache的保障机制,如果cache失败,就使用checkpoint的数据。
使用checkpoint的优点在于提高了Spark作业的可靠性,一旦缓存出现问题,不需要重新计算数据,缺点在于,checkpoint时需要将数据写入HDFS等文件系统,对性能的消耗较大