四、spark的shuffle

1、shuffle过程
2、shuffle机制
3、Spark Shuffle相关问题总结
4、task的生成
5、Spark Shuffle参数调优
博文链接:https://blog.csdn.net/murphyZ/article/details/88202446

1、shuffle过程

1.1)、shuffle过程
如下图:
spark_shuffle
了解Spark的shuffle过程:
shuffle操作是在Spark操作中调用了一些特殊的算子才会触发的一种操作,
shuffle操作会导致大量的数据不同的节点之间进行传输,因此,shuffle过程
是Spark中最复杂、最消耗性能的一种操作。

比如:
reduceByKey算子会将上一个RDD中的每个key对应的所有value都聚合成一个value,然后生成一个新的RDD,新的RDD的元素类型就是<key, value>的格式,每个key对应一个聚合起来的value,在这里,最大的问题在于,对于上一个RDD来说,并不是一个key对应的所有的value都在一个partition中的,更不太可能key的所有value都在一个节点上,对于这种情况,就必须在集群中将各个节点上同一个key对应的values统一传输到一个节点上进行聚合处理,这个过程势必会发生大量的网络IO

1.2)、spark shuffle会发生shuffle write和 shuffle read
shuffle过程中分为shuffle writeshuffle read,而且会在不同的stage中进行的shuffle write发生在map task,把要shuffle的数据写到磁盘的过程, shuffle read发生在reduce task,是指下游RDD读取上游RDD的过程,也就是reduce task读取
并合并的过程

1.3)、会导致shuffle的算子
1、byKey类的算子:比如reduceByKey、groupByKey、sortByKey、aggregateByKey、combineByKey
2、repartition类的算子:比如repartition(少量分区变成多个分区会发生shuffle)、repartitionAndSortWithinPartitions、coalesce(需要指定是否发生shuffle)、partitionBy
3、join类的算子:比如join(先groupByKey后再join就不会发生shuffle)、cogroup
注意:首先对于上述操作,能不用shuffle操作,就尽量不用,尽量使用不发生shuffle的操作。其次,如果使用了shuffle操作,那么肯定要进行shuffle的调优,甚至是解决遇到的数据倾斜问题

shuffle(总结):
在进行一个key对应的values的聚合时,首先,上一个stage的每个map task就必须保证将自己处理的当前分区中的数据相同key写入一个分区文件中,可能会多个不同的分区文件,接着下一个stage的reduce task就必须从上一个stage的所有task所在的节点上,将各个task写入的多个分区文件中找到属于自己的分区文件,然后将属于自己的分区数据拉取过来,这样就可以保证每个key对应的所有values都汇聚到一个节点上进行处理和聚合,这个过程就称之为shuffle!!!

2、shuffle机制在这里插入图片描述

3、Spark Shuffle相关问题总结

3.1)、shuffle过程中的分区排序问题
默认情况下,shuffle操作是不会对每个分区中的数据进行排序的
如果想要对每个分区中的数据进行排序,可以使用三种方法:
1、使用mapPartitions算子把每个partition取出来进行排序
2、使用repartitionAndSortWithinPartitions(该算子是对RDD进行重分区的算子),在重分区的过程中同时就进行分区内数据的排序
3、使用sortByKey对所有分区的数据进行全局排序
注意:以上三种方法,mapPartitions代价比较小,因为不需要进行额外的shuffle操作,repartitionAndSortWithinPartitions和sortByKey可能会进行额外的shuffle操作,因此性能并不是很高。

3.2)、为什么会发生shuffle write (写)过程 ?
1、为了避免大量的分区文件占用大量的内存而导致oom。
2、保存到磁盘可以保证数据的安全性。

3.3)、shuffle操作过程为什么最需要优化?
shuffle操作是spark中唯一最消耗性能的过程,因此也就成了最需要进行性能调优的地方,最需要解决线上报错的地方,也就是唯一可能出现数据倾斜的地方

3.4)、实时shuffle操作与stage的联系
为了实时shuffle操作,spark才有stage的概念,在发生shuffle操作的算子中,需要进行stage的划分
shuffle操作的前半部分,属于上一个stage的范围,通常称之为map task,
shuffle操作的后半部分,属于下一个stage的范围,通常称之为reduce task,
其中map task负责数据的组织,也就是将同一个key对应的value都写入同一个下游task对应的分区文件中,
其中reduce task负责数据的聚合,也就是将上一个stage的task所在的节点上,将属于自己的各个分区文件
都拉取过来进行聚合。

3.5)、spark shuffle的优化体现在哪些方面(加分析)?
map task会将数据先保存在内存中,如果内存不够时,就溢写到磁盘文件中,
reduce task会读取各个节点上属于自己的分区磁盘文件到自己节点的内存中进行聚合。

由此可见,shuffle操作会消耗大量的内存,因为无论是网络传输数据之前还是之后,
都会使用大量内存中数据结构来实施聚合操作,
在聚合过程中,如果内存不够,只能溢写到磁盘文件中去,
此时就会发生大量的网络IO,降低性能。

此外,shuffle过程中,会产生大量的中间文件,也就是map side写入的大量分区文件,
这些文件会一直保留着,直到RDD不再被使用,而且被gc回收掉了,才会去清理中间文件,
这主要是为了:如果要重新计算shuffle后RDD,那么map side不需要重新再做一次磁盘写操作,
但是这种情况下,如果在应用程序中一直保留着对RDD的引用,
导致很长的时间以后才会进行回收操作,
保存中间文件的目录,由spark.local.dir属性指定

所以,spark性能的消耗体现在:内存的消耗、磁盘IO、网络的IO

4、task的生成

task的生成,一定是在stage范围内,不会跨越stage
task的数量可以这样计算:RDD分区的数量乘以stage的数量(必须是没有重分区的操作)
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值