看完本篇文章,下次遇到Spark报错就迎刃而解了,Spark调优再也不用求人解决了

今天和各位聊一聊Spark使用中遇到的问题之Spark调优

小伙伴们一定在生产环境中遇到过Spark各种各样的问题,比如在Spark UI界面发现某个Task运行特别缓慢,还存在着内存溢出问题,又比如产生了数据倾斜,某个task处理的数据特别多,拖慢了整个任务的执行时间 等等,我们该如何下手解决这一系列棘手的问题呢?
首先我们通过以下几个方面进行调优
资源方面
JVM方面
算子方面
Shuffle阶段
数据倾斜方面

1.资源方面

1.1 给任务分配充足的资源

在yarn提交任务的时候配置一下参数

--executor-memory 
--executor-core 
--driver-memory

1.2 提高Task并行度

官方文档推荐任务提交的Task并行度是总的CPU 核数的 2-3倍
为什么这样子设计呢?因为有的Task 执行速度快,有的Task执行速度慢,执行完任务有的Task就空闲着,导致资源的浪费,执行完当前任务还可以继续执行其余的任务
参数设置

new SparkConf().set("spark.default.parallelism","500")

1.3 对多次使用的RDD持久化 (cache/presist)

1.4 使用广播变量

将数据量不是特别大的数据,收集到Driver端进行广播,每个executor内存中就会有一份数据,task只需要向BlockManager获取即可,不用向Driver拉取数据
参数设置

sprak.sparkcontext.broadcast

1.5 序列化

将对象转换为字节流,本质也可以理解为将链表的非连续空间转为连续空间存储的数组,可以将数据进行流式传输或者块存储,反序列化就是将字节流转为对象。
spark 中的序列化常见于:
进程间通讯,不同节点的数据传输;
数据持久化到磁盘
在 spark 中扮演非常重要的角色,序列化和反序列化的程度会影响到数据传输速度,甚至影响集群的传输效率,因此,高效的序列化方法有 2 点好处:a.提升数据传输速度,b.提升数据读写 IO 效率。
使用kryo 序列化,相对于Java的serializer 序列化,kryo序列化速度快,数据占用内存少,网络传输数据量变小了,RDD持久化的时候占用的内存就少了。
参数设置

spark.conf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer").registerKryoClass(new class())

2 JVM方面

2.1 调节堆外内存比例

spark 在运行任务的时候将堆外内存划分为两份,其中60%的内存给数据缓存使用,剩下的40%用作函数运算,如果用作缓存的数据量不是特别大,算子运行时频繁的创建对象,内存又不大,频繁的minorgc 甚至,full spark 频繁停止工作,可以适当的调整比例。
参数设置

set(spark.storage.memoryFraction,0.6)

2.2 调节堆外内存大小

通常情况在运行任务量较大的作业时,spark任务时不时报错,shuffle output file not found,executor xx.xx.xx.xx lost / task lost / out of memory
可能是堆外内存不够用了,导致executor 在运行的时候可能会内存溢出,可能导致后面stage拉取关联数据的时候,需要从executor拉取数据文件,但是executor已经挂掉了,关联的block manager 也没有了,所以才会报错,针对这种情况可以调节一下executor堆外内存,对于性能来说也许会有一定过得提升。
参数设置

--conf spark.yarn.executor.memoryOverhead = 4096

不设置默认 300m,通常在项目中,这里都会出现问题,导致spark作业一直崩溃无法正常作业,此时就应该去调节这个参数,至少为1G,甚至高达30G
spark底层shuffle的传输方式是使用netty传输,netty在网络传输的过程中会使用堆外内存进行spark的读写操作(零拷贝)。所以使用了堆外内存,默认情况下,这个堆外内存上限是每个executor的内存大小的10%。

2.3 调节堆外等候时间

executor在进行shuffle write,优先从自己本地关联mapoutputworker中获取某份数据,如果本地block manager没有的话,那么会通过Transferservice,去远程连接其他节点上executor的block manager 去获取,尝试建立远程的网络连接,并且去拉取数据。频繁创建对象让JVM堆外内存溢满,进行垃圾回收,如何正好那个executor的JVM正在垃圾回收,处于垃圾回收的过程中,所有工作线程全部停止,相当于只要一旦进行垃圾回收,spark-executor将停止作业,无法提供响应,spark默认网络连接的超时时间为60S,如果60S都无法建立连接的话,那么这个task就失败了,task失败了就会出现shuffle file canot find
参数配置

--conf spark.core.connection.ack.wait.timeout=300s

3算子方面

3.1 reducebykey

使用reducebykey代替 groupbykey ,reducebykey会在map端做局部聚合,相当于combiner,在本地进行聚合后,在map端在shuffle的数据量就变少了,减少磁盘 IO,也减少磁盘空间的占用。下一个 stage, 拉取数据的量, 也就变少了,提高了网络之间的传输
使用场景

对数据做累加

3.2 mappartition

使用mappartition代替map方法,foreachpartition代替foreach 这两个算子都是在一个分区执行一次,但是注意数据太大也会报oom

4 数据倾斜方面

4.1 通过repartition,spark.default.parallelism和自定义分区

适用场景:大量的数据分配到相同的task中,导致倾斜
如果是sql的话,调整spark.sql.shuffle.partitions增大并行数量,从而将倾斜数据分配到更多的task减少倾斜
优点:对于部分key倾斜,可以通过增大并行数,或者自定义分区,将数据分布的更加均匀,减少数据倾斜
缺点:对于单个key倾斜,只能根据业务自定分区,减少数据倾斜

4.2 通过增大spark.sql.autoBroadcastJoinThreshold

大表根小表进行join的时候,一般需要进行shuffle将所有key打散,发送到reduce进行计算,在这个过程中,非常有可能小表中的key在大表中占比较大,需要fetch read导致造成大量的网络和磁盘IO,导致效率低下,甚至OOM,导致任务失败,因此我们可以避免shuffle,在map端进行进行join,把小表的数据通过broadcast的方式发送到executor,之后直接在map 进行join计算,提高效率
适用场景:两个数据集差别较大,并且出现task数据倾斜,较小的数据集可以放到内存中map中进行join

解决方案:通过增大spark.sql.autoBroadcastJoinThreshold 阈值默认10M

优点:减少大的数据集shuffle,从而导致数据倾斜
缺点: join小表的数据需要足够小,能放到executor storage memory中

4.3 sample采样,对倾斜key单独进行处理

shuffle的过程中,由于单个或者某几个key倾斜,导致在shuffle的过程中,数据分布不均匀,这种情况增大并行对数据倾斜作用不太,即使我们的task数量1000个,仍然倾斜,这时候需要我们对倾斜的key进行单独处理
通过sample采样对key进行聚合groupby,然后count算出key记录数多的key,将rdd数据按照倾斜的key进行filter过滤,分开计算
对于倾斜的数据我们通过添加随机前缀进行join得到dataset1
对于非倾斜的数据我们直接进行join得到dataset2
最后将两部分的数据使用union进行合并,得到最终结果

5 shuffle方面

5.1 开启map端文件的合并机制

spark任务中,task数量多,产生的文件数量太多了,每个stage都要去拉去上一个stage的数据,走网络传输的话,拖慢的整个程序的运行时间
参数设置

New sparkConf () .set(spark.shuffle.consolidatafile",true)
  • 0
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:像素格子 设计师:CSDN官方博客 返回首页
评论

打赏作者

大数据学习僧

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值