Shuffle描述是一个过程,表现出的是多对多的依赖关系。Shuffle是连接map阶段和Reduce阶段的纽带,每个Reduce Task都会从Map Task产生的数据里读取其中的一片数据。Shuffle通常分为两个部分:Map阶段的数据准备和Reduce阶段的数据副本。
Map阶段根据Reduce阶段的Task数量来决定每个Map Task输出的数据分片的个数,这些数据分片可能保存在内存中或者磁盘上,这些分片的存在形式可能是每个分片一个文件,也可能是多个分片放在一个数据文件中,外加一个索引来记录每个分片在数据文件中的偏移量。(RDD中的窄依赖除外,恰好是一对一的)
1、 Shuffle写
Spark中Shuffle输出的ShuffleMapTask会为每个ResultTask创建对应的Bucket,ShuffleMapTask产生的结果会根据设置的partitionner得到对应的BucketId.然后填充到对应的Bucket中去,所以每个ShuffleMapTask创建Bucket的数据是和ResultTask的数目相等的。
ShuffleMapTask创建的Bucket对应磁盘上的一个文件,用于存储结果,此文件也被成为BlockFile.通过spark.shuffle.file.buffer.kb属性配置的缓冲区就是用来创建FastBufferedOutputStream输出流的。如果在配置文件中设置了spark.shuffle.consolidateFiles属性为true,则ShuffleMapTask所产生的Bucket就不一定单独对应一个文件了,而是对应文件的一部分,这样做会大大减少产生的BlockFile文件数量。
2、 Shuffle读
Spark可以通过两种方式读数据,一种是普通的socket方式,另一种是使用Netty框架。Netty方式可以通过配置spark.shuffle.use.netty属性为true启动。Netty框架时,BlockManager会创建ShuffleSender专门用于发送数据,如果ResultTask所需要的数据恰好在本节点,则直接去磁盘上读即可,不再通过网络获取。MapReduce取数据时,即使数据在本地还是要走一遍网络传输。