map端的多个文件会被汇总成一个文件,这样就大大减少了磁盘IO的压力。

 

ByPassMergeSortShuffleWriter流程示例如下:

spark df 合并列 spark merge_输出流

使用这种Shuffle方式需要满足两个条件:

  1. 没有定义mapSideCombine(map端对数据agg)
  2. Partition数要小于一定的数量,默认是200
  3. 还看到说不能指定ordering…这个我在代码里面没找到,个人理解为没有这个限制,如果有人知道的话,麻烦和我说下,感激!

spark df 合并列 spark merge_临时文件_02

限制分区的数量???网上找到的说法是因为在合并文件的时候会并发打开所有分区的临时文件,会对文件系统造成很大的压力,所以分区数量不能过多。个人看代码的时候,发现合并临时Shuffle文件的时候不是并发打开的…这里不太清楚,麻烦知道的大神和我说下,感谢!

这里顺便再提一下,如果不指定Partition数量的话,默认的并发至少是2(Partition数,一般你写程序的话,totalCoreCount不会小于2的吧):

spark df 合并列 spark merge_文件系统_03

 

ByPassMergeSortShuffleWriter流程源码分析:

1.将每个Partition的数据分别写到对应的临时文件中

首先创建一个long[numPartitions],记录每个partition的长度,用于在正式的Shuffle文件中定位每个Partition的起始和结束位置

spark df 合并列 spark merge_临时文件_04

 

    每个Partition会对应创建一个DiskBlockObjectWriter和FileSegment,前者用于往这个Partition对应的临时Shuffle文件中写入数据,后者就是临时Shuffle文件

spark df 合并列 spark merge_文件系统_05

spark df 合并列 spark merge_输出流_06

 

 

2.将临时Shuffle文件合并成最终的Shuffle文件,并建立索引文件

spark df 合并列 spark merge_spark df 合并列_07

以便Reduce任务拉取用。

 

writePartitionedFile(temp)合并临时Shuffle文件:

首先打开正式Shuffle文件的输出流:

spark df 合并列 spark merge_spark df 合并列_08

 

调用Utils.copyStream方法,将输入流中的字节数据拷贝到输出流中(就是写文件的操作):

spark df 合并列 spark merge_spark df 合并列_09

 

补充:Spark最初的HashShuffle介绍:

    Spark最初使用的是HashBaseShuffle,它会有过多小文件的问题,然后社区改进了一个版本称之为Consolidation Shuffle,但还是存在文件过多的问题,这里对它们进行一些简单的介绍,然后就会明白为什么会放弃这两种Shuffle方式。

 

HashBaseShuffle:

    Spark最开始使用的是HashBaseShuffle,每一个MapTask都会根据Reduce的数量创建一个文件。即有3个MapTask,3个ReduceTask,那么就会产生9个小文件,图示如下:

spark df 合并列 spark merge_临时文件_10

小文件太多的话,对文件系统造成的压力会很大,而且也不利于IO吞吐量,所以后面就进行了优化,把同一个core上运行的多个MapTask的输出合并到同一个文件里面,这种Shuffle方式称为Consolidation Shuffle。

 

Consolidation Shuffle:

同一个Core上运行的所有MapTask输出的FileSegment会被合并形成一个ShuffleBlockFile,这样就减少了文件的数量。

举个例子:比如一个Job有4个Map和3个reduce:

(1) 如果集群有4个节点,每个节点空闲了一个core,则4个Map会调度到这3个节点上执行,每个Map都会创建3个Shuffle文件,总共创建12个Shuffle文件;

(2) 如果集群有2个节点,每个节点空闲了一个core,则2个Map先调度到这2个节点上执行,每个Map都会创建3个Shuffle文件,然后其中一个节点执行完Map之后又调度执行另一个Map,则这个Map不会创建新的Shuffle文件,而是把结果输出追加到之前Map创建的Shuffle文件中;总共创建6个Shuffle文件;

图示如下:

spark df 合并列 spark merge_输出流_11

 

 

 

 

参考:

    (Shuffle流程示例图)

    (HashShuffle的流程示意图)