spark调优

6 篇文章 0 订阅
1 篇文章 0 订阅

学习美团的spark性能优化指南笔记。

参考:Spark性能优化指南——基础篇 - 美团技术团队

优化主要从4个方面进行:

        1. 开发调优

  • 避免创建重复的RDD

当多个算子都用到一个RDD的时候,尽量只创建一个RDD,算子只使用一个RDD

  • 尽可能复用同一个RDD

不要因为要用一些数据,创建过多的RDD,比如:

// 错误的做法。

// 有一个<Long, String>格式的RDD,即rdd1。
// 接着由于业务需要,对rdd1执行了一个map操作,创建了一个rdd2,而rdd2中的数据仅仅是rdd1中的value值而已,也就是说,rdd2是rdd1的子集。
JavaPairRDD<Long, String> rdd1 = ...
JavaRDD<String> rdd2 = rdd1.map(...)

// 分别对rdd1和rdd2执行了不同的算子操作。
rdd1.reduceByKey(...)
rdd2.map(...)

// 正确的做法。

// 上面这个case中,其实rdd1和rdd2的区别无非就是数据格式不同而已,rdd2的数据完全就是rdd1的子集而已,却创建了两个rdd,并对两个rdd都执行了一次算子操作。
// 此时会因为对rdd1执行map算子来创建rdd2,而多执行一次算子操作,进而增加性能开销。

// 其实在这种情况下完全可以复用同一个RDD。
// 我们可以使用rdd1,既做reduceByKey操作,也做map操作。
// 在进行第二个map操作时,只使用每个数据的tuple._2,也就是rdd1中的value值,即可。
JavaPairRDD<Long, String> rdd1 = ...
rdd1.reduceByKey(...)
rdd1.map(tuple._2...)

// 第二种方式相较于第一种方式而言,很明显减少了一次rdd2的计算开销。
// 但是到这里为止,优化还没有结束,对rdd1我们还是执行了两次算子操作,rdd1实际上还是会被计算两次。
// 因此还需要配合“原则三:对多次使用的RDD进行持久化”进行使用,才能保证一个RDD被多次使用时只被计算一次。
  • 对多次使用的RDD进行持久化

spark对于一个RDD执行多次算子的原理是每次对一个RDD执行一个算子操作时,都会重新从源头计算一遍,算出RDD,然后再对RDD执行你的算子,这样的话,RDD就重复计算了。所以需要对使用的RDD进行持久化。两个方法persist(参数), chache(), persist(MEMORY_ONLY) = cache(),数据太大时,MEMORY_ONLY会发生内存溢出,可使用MEMORY_ONLY_SER(会将RDD数据序列化后再保存到内存中,可以大大减少数据的大小),参数中后缀是2的,表示要备份一份,慎用。

  •  尽量避免使用shuffle类算子

spark作业中最消耗性能的地方就是shuffle过程,当一个大文件和一个小文件进行的join的时候,可以将小文件进行广播(broadcast),这样就避免了把数据从其他节点拉取到一个节点的情况

  • 使用map-side预聚合的shuffle操作

预聚合就是在进行shuffle算子的时候,先在每个节点进行一次聚合计算,之后再进行聚合(拉取到统一节点)这样数据量会少很多。尽量使用reduceByKey,aggregateByKey代替groupBykey

  • 使用高性能的算子

        a. 使用reduceByKey,aggregateByKey代替groupBykey

        b. 使用mapPartitions替代普通的map, mapPartitions一次处理一个partition所有的数据,而不是一次函数处理一条,但是可能发生内存不够

        c. 使用foreachPartition替换foreach.类似上述方法,很明显的案例,往mysql写数据的时候,如果使用foreach一条一条往mysql中写数据,每次写入创建一个数据库连接,性能非常低下,但是使用foreachPartition,性能可以提升很多。

        d.filter之后进行coalesce操作

        e. repartitionAndSortWithinPartitions替代repartition与sort类操作。进行分区的同时进行排序操作。

        2. 资源调优

        3. 数据倾斜调优

                现象:个别task执行极慢

                原因:在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,此时如果某个key对应的数据量特别大,就会发生数据倾斜。

                方案一:通过ETL预处理

                方案二:过滤掉不需要的倾斜的key

                方案三:提高shuffle的并发度

                方案四:两阶段聚合,先进行一次预聚合,再进行一次全局聚合

                方案五:大表和小表进行join的时候,将小表广播出去,将reduce join 转化为map join

                方案六:倾斜key分拆join,加随机数,扩容

                适用场景:两个量很大的数据进行join A join B,且倾斜的key不多

                  ​​​​​​​实现思路:

                ​​​​​​​   1. 通过sample算子进行采样,计算出量很大的那几个key;2. 将造成倾斜的key的数据和其他正常的数据形成a1,a2两份数据;3. 将a1的key上随机打上n以内的随机数,B的key上也打上随机数,每条数据膨胀成n条数据Bn(扩容), a1 join Bn; 4. a2正常进行join即可;5. 最后将两份数据union 到一起。(Bn 扩容成n倍, 这样a1中的key不管打上的随机数是多少,都可以在Bn中找到)                

                方案七:随机数,扩容RDD进行join

                  适用场景:两个量很大的数据进行join A join B,且倾斜的key很多

                  实现思路:

                类似方案六,只是A不进行数据拆分,而是将A的所有key上都打上n以内的随机数,将B扩容n倍,然后进行join即可。

        4. shuffle调优

set spark.sql.caseSensitive=FALSE; 设置不区分大小写

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

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值