spark-troubleshooting

1:shuffle reduce端缓冲大小以避免OOM

spark.reducer.maxSizeInFlight,48 默认

spark.reducer.maxSizeInFlight,24

 

当reduce发生OOM时,可以适当调小 reduce缓冲区的大小,这样每次拉取的文件变少,处理的数据变少,便不会内存溢出。但是导致处理数据的性能变弱。

这是一种一执牺牲性能的方式,换取程序能够正常的执行。

 

当资源都是足够充足的时候,调大reduce缓冲区的大小,达到能好的处理性能。

减少网络传输消耗的性能,reduce执行次数消耗的性能。

 

 

2.JVM GC导致的shuffle文件拉取失败

spark.shuffle.io.maxRetries 3

 

第一个参数,意思就是说,shuffle文件拉取的时候,如果没有拉取到(拉取失败),最多或重试几次(会重新拉取几次文件),默认是3次。

 

spark.shuffle.io.retryWait 5s

 

第二个参数,意思就是说,每一次重试拉取文件的时间间隔,默认是5s钟。

 

默认情况下,假如说第一个stage的executor正在进行漫长的full gc。第二个stage的executor尝试去拉取文件,结果没有拉取到,默认情况下,会反复重试拉取3次,每次间隔是五秒钟。最多只会等待3 * 5s = 15s。如果15s内,没有拉取到shuffle file。就会报出shuffle file not found。

 

针对这种情况,我们完全可以进行预备性的参数调节。增大上述两个参数的值,达到比较大的一个值,尽量保证第二个stage的task,一定能够拉取到上一个stage的输出文件。避免报shuffle file not found。然后可能会重新提交stage和task去执行。那样反而对性能也不好。

 

spark.shuffle.io.maxRetries 60

spark.shuffle.io.retryWait 60s

 

最多可以忍受1个小时没有拉取到shuffle file。只是去设置一个最大的可能的值。full gc不可能1个小时都没结束吧。

 

这样呢,就可以尽量避免因为gc导致的shuffle file not found,无法拉取到的问题。

 

3.解决YARN队列资源不足导致的application直接失败

分配更多的资源。

一个资源队列中保证只有一个spark作业,用线程池(线程数为1)

将长期执行的spark作业与短时间作业分开到不同spark队列中执行

 

 

4.解决各种序列化导致的报错

5.解决算子函数返回NULL导致的问题

在有些算子函数里面,是需要我们有一个返回值的。但是,有时候,我们可能对某些值,就是不想有什么返回值。我们如果直接返回NULL的话,那么可以不幸的告诉大家,是不行的,会报错的。

 

Scala.Math(NULL),异常

 

如果碰到你的确是对于某些值,不想要有返回值的话,有一个解决的办法:

 

1、在返回的时候,返回一些特殊的值,不要返回null,比如“-999”

2、在通过算子获取到了一个RDD之后,可以对这个RDD执行filter操作,进行数据过滤。filter内,可以对数据进行判定,如果是-999,那么就返回false,给过滤掉就可以了。

3、大家不要忘了,之前咱们讲过的那个算子调优里面的coalesce算子,在filter之后,可以使用coalesce算子压缩一下RDD的partition的数量,让各个partition的数据比较紧凑一些。也能提升一些性能。

 

 

6.解决yarn-client模式导致的网卡流量激增问题

 

7.解决yarn-cluster模式的JVM栈内存溢出问题

实践经验,碰到的yarn-cluster的问题:

 

有的时候,运行一些包含了spark sql的spark作业,可能会碰到yarn-client模式下,可以正常提交运行;yarn-cluster模式下,可能是无法提交运行的,会报出JVM的PermGen(永久代)的内存溢出,OOM。

 

yarn-client模式下,driver是运行在本地机器上的,spark使用的JVM的PermGen的配置,是本地的spark-class文件(spark客户端是默认有配置的),JVM的永久代的大小是128M,这个是没有问题的;但是呢,在yarn-cluster模式下,driver是运行在yarn集群的某个节点上的,使用的是没有经过配置的默认设置(PermGen永久代大小),82M。

 

spark-sql,它的内部是要进行很复杂的SQL的语义解析、语法树的转换等等,特别复杂,在这种复杂的情况下,如果说你的sql本身特别复杂的话,很可能会比较导致性能的消耗,内存的消耗。可能对PermGen永久代的占用会比较大。

 

所以,此时,如果对永久代的占用需求,超过了82M的话,但是呢又在128M以内;就会出现如上所述的问题,yarn-client模式下,默认是128M,这个还能运行;如果在yarn-cluster模式下,默认是82M,就有问题了。会报出PermGen Out of Memory error log。

 

如何解决这种问题?

 

既然是JVM的PermGen永久代内存溢出,那么就是内存不够用。咱们呢,就给yarn-cluster模式下的,driver的PermGen多设置一些。

 

spark-submit脚本中,加入以下配置即可:

--conf spark.driver.extraJavaOptions="-XX:PermSize=128M -XX:MaxPermSize=256M"

 

这个就设置了driver永久代的大小,默认是128M,最大是256M。那么,这样的话,就可以基本保证你的spark作业不会出现上述的yarn-cluster模式导致的永久代内存溢出的问题。

 

spark sql,sql,要注意,一个问题

 

sql,有大量的or语句。比如where keywords='' or keywords='' or keywords=''

当达到or语句,有成百上千的时候,此时可能就会出现一个driver端的jvm stack overflow,JVM栈内存溢出的问题

 

JVM栈内存溢出,基本上就是由于调用的方法层级过多,因为产生了大量的,非常深的,超出了JVM栈深度限制的,递归。递归方法。我们的猜测,spark sql,有大量or语句的时候,spark sql内部源码中,在解析sql,比如转换成语法树,或者进行执行计划的生成的时候,对or的处理是递归。or特别多的话,就会发生大量的递归。

 

JVM Stack Memory Overflow,栈内存溢出。

 

这种时候,建议不要搞那么复杂的spark sql语句。采用替代方案:将一条sql语句,拆解成多条sql语句来执行。每条sql语句,就只有100个or子句以内;一条一条SQL语句来执行。根据生产环境

 

 

8.错误的持久化方式以及checkpoint的使用

错误的持久化使用方式:

 

usersRDD,想要对这个RDD做一个cache,希望能够在后面多次使用这个RDD的时候,不用反复重新计算RDD;可以直接使用通过各个节点上的executor的BlockManager管理的内存 / 磁盘上的数据,避免重新反复计算RDD。

 

usersRDD.cache()

usersRDD.count()

usersRDD.take()

 

上面这种方式,不要说会不会生效了,实际上是会报错的。会报什么错误呢?会报一大堆file not found的错误。

 

正确的持久化使用方式:

 

usersRDD

usersRDD = usersRDD.cache()

val cachedUsersRDD = usersRDD.cache()

 

之后再去使用usersRDD,或者cachedUsersRDD,就可以了。就不会报错了。所以说,这个是咱们的持久化的正确的使用方式。

 

 

 

checkpoint原理:

 

1、在代码中,用SparkContext,设置一个checkpoint目录,可以是一个容错文件系统的目录,比如hdfs;

2、在代码中,对需要进行checkpoint的rdd,执行RDD.checkpoint();

3、RDDCheckpointData(spark内部的API),接管你的RDD,会标记为marked for checkpoint,准备进行checkpoint

4、你的job运行完之后,会调用一个finalRDD.doCheckpoint()方法,会顺着rdd lineage,回溯扫描,发现有标记为待checkpoint的rdd,就会进行二次标记,inProgressCheckpoint,正在接受checkpoint操作

5、job执行完之后,就会启动一个内部的新job,去将标记为inProgressCheckpoint的rdd的数据,都写入hdfs文件中。(备注,如果rdd之前cache过,会直接从缓存中获取数据,写入hdfs中;如果没有cache过,那么就会重新计算一遍这个rdd,再checkpoint)

6、将checkpoint过的rdd之前的依赖rdd,改成一个CheckpointRDD*,强制改变你的rdd的lineage。后面如果rdd的cache数据获取失败,直接会通过它的上游CheckpointRDD,去容错的文件系统,比如hdfs,中,获取checkpoint的数据。

 

 

说一下checkpoint的使用

 

1、SparkContext,设置checkpoint目录

2、对RDD执行checkpoint操作

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值