SparkCore之shuffle

Spark之shuffle

什么是shuffle

Spark中的shuffle是指将不同的key重新进行分配的一个中间过程,首先Spark有3种类型的算子会产生shuffle:

重新分区操作,例如:repartition&coalesce

RDD的join操作, 例如:cogroup&join

bykey操作,例如:reduceByKey…

为什么会产生shuffle,shuffle中具体发生了什么事,我们通过reduceByKey()算子进行分析

首先我们写一段简单的代码:

//假如source的分区数为1,在source的时候指定
val rdd: RDD[(String, Int)] = source.flatMap(_.split("\\s"))
      .filter(!_.isEmpty) //1 to 1
      .map((_, 1))   //1 to 1 
      .reduceByKey(_ + _, 2) // n to 1\ 1 to n \ n to n
  
  //rdd的分区数为2

在以上代码中,在reduceByKey的时候,相当于把之前source 1个分区的数据分成2份到rdd的2个分区,在这个重新分配的过程中,source的单个分区的数据会交给不同的task进行处理,这里根据血缘关系,就有以下推理:

# 1.source为父RDD
# 2.rdd为子RDD
# 3.rdd是依赖于source,当执行reduce操作时,source的单个分区中的不同key的数据会分散到rdd的不同分区中,source=>rdd数据分区重新分配的处理过程就可以理解成shuffle
# 4.rdd与source之间的依赖就是宽依赖,用来切分stages(taskSets)

shuffle的性能影响

shuffle是一个及其昂贵的操作过程,虽然没有mapred的shuffle那么昂贵,但是还是会涉及到:磁盘IO、数据序列化、网络IO等相关的性能消耗,为了组织shuffle的数据,spark会生成 task-sets(map tasks去组织数据,reduce tasks去聚合数据,这个与MR中的性质其实是异曲同工的)

shuffle过程

在spark1.6之前是有HashShuffle的,但是在1.6之后默认的shuffle方式改成了SortedShuffle

sorted shuffle是什么

shuffle是map操作与reduce操作之间的中间操作,shuffle过程中,map tasks组织的数据将会缓存在execute的缓存buffer内存中,当达到buffer阈值时,这些数据会基于目标分区的个数(即reduce中指定的并行度)进行排序并且写入到单个文件中,在reduce端,tasks读取对应hash值的key的数据的数据块(sorted blocks)。

一、shuffle操作会消耗大量的堆内存,因为在转移数据前后会雇佣对应的内存数据结构组织并缓存数据,具体来讲,reduceByKey aggregateBykey会在map端创建这样的数据结构,bykey操作创建转换之后的数据结构在reduce端,当数据量超过了缓存内容的阈值,那么会将这些数据或者表溢写到磁盘,从而产生额外的IO开销、增加垃圾回收。

二、shuffle还会在磁盘上产生大量的中间文件,从spark1.3开始,将保留对应的文件直到对应的RDD不再被引用并且进行GC之后才会删除,这样做时为了在追溯血缘关系时无需重新创建shuffle文件,如果应用程序保留了对这些RDD的引用,或者young GC不经常启动,很有可能造成full GC,造成stop the world的局面,这意味着长时间运行的Spark作业可能会占用大量的磁盘空间。临时的文件存储目录可以通过spark.local.dir在sparkconf进行指定

shuffle行为的配置指南可以参考:spark-shuffle配置指南

//TODO 今后会持续更新,并配上相应的图解

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值