Spark 的shuffle流程框架以及源码详解(匠心巨作)(1)

spark 作为大数据的处理平台,因其优先使用内存资源,可以快速处理海量数据。spark 虽然号称内存计算,但是,并不是所有阶段都是在内存中完成的,spark shuffle的这一个环节是必须要写磁盘的。所以一个spark程序性能的高低,shuffle 过程有着决定性的作用。本编博客将会详细的分析spark 的shuffle过程,内容主要有以下几个方面,spark shuffle 的发展,shuffle中使用的几种数据结构,shuffle的执行流程ShuffleWriter(包括BypassMergeSortShuffleWriter,SortShuffleWriter以及UnsafeShuffleWriter)和ShuffleReader。

    1.  Shuffle 的作用

      Spark Shuffle 的过程描述着数据从ShuffleMapTask端传输到ShuffleReduceTask端的过程,这个一阶可能涉及的过程包括数据的排序,聚合,溢写,合并,传输,磁盘IO,网络的IO等等。Shuffle是连接MapTaskReduceTask间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环节Shuffle的性能高低直接影响了整个程序的性能和吞吐量。通常shuffle分为两部分:Map阶段的数据准(ShuffleMapTask)Reduce(ShuffleReduceTask)段的数据拷贝处理。一般将Map端的Shuffle称之为Shuffle Write,在Reduce端的Shuffle称之为Shuffle Read

     2.  Shuffle 的发展

    

上图是Spark Shuffle的发展史,在spark 0.8版本以前使用的shuffle方式是HashShuffle,这种方式如下图所示:

 

HashShuffle 过程中会创建大量的磁盘小文件,每个ShuffleMapTask 都会根据ShuffelReduceTask 的分区数量,创建相应个数的磁盘小文件,创建的磁盘小文件的个数是M*R ,其中M是ShuffleMapTask 的数量,R是ShuffleReduceTask 的数量。上图中产生的小文件个数为4*2=8个小文件。一般在处理大数据时,ShuffleMapTask和ShuffleReduceTask的数量是非常之多的,创建的磁盘文件数量相应也是很多,因此这么多的文件要写磁盘,再从磁盘读出来,不仅会占用大量的时间,每个磁盘文件记录的句柄都会保存在内存中,因此也会占用很大的内存空间,频繁的打开和关闭文件,会导致频繁的GC操作,很容易会出现OOM的情况。

因此,为了缓解这种情况,在spark 0.8.1版本中,引入了Consolidation机制,该机制是对HashShuffle的一种优化,原理以及框架如下图所示:

Consolidation机制,在同一个Executor中的ShuffleMapTask 共用一个bucket,也就是在同一个Executor 中第一个ShuffleMapTask会创建相应的bucket,后面再执行的ShuffleMapTask不会再创建bucket,而是和前面已经创建好的bucket共用,把数据直接添加到这个bucket后面即可,最后形成一个文件。这种机制产生的磁盘文件数量为E*R,其中E是Executor的数量,R 是ShuffleReduceTask的数量。同样是执行4个ShuffleMapTask,最后产生4个磁盘文件,相比较于HashShuffle ,产生的磁盘小文件数量减半,大大减少了磁盘文件的数量。 在一定程度上减少了在Shuffle过程中读写磁盘文件的个数,减少了内存的占用,降低OOM的风险,但是如果一个Job的ShuffleReduceTask 的数量很多,虽然Consolidation机制能够减少一定的磁盘文件,但是仍然有数量可观的磁盘文件的产生。

在spark 0.9 版本中,引入了ExternalAppendOnlyMap 的数据结构,这种结构是相较于AppendOnlyMap的数据结构,前者在内存中接收数据,当达到一定的阈值后,会把数据溢写到磁盘,后者则不会把数据溢写到磁盘,因此AppendOnlyMap 这种数据结构容易导致OOM,引入ExternalAppendOnlyMap后,可以有效降低OOM 的风险。

由于HashShuffle会产生很多的磁盘文件,引入Consolidation机制虽然在一定程度上减少了磁盘文件数量,但是不足以有效提高Shuffle的性能,因此在Spark 1.1版本中,引入了SortShuffle,这种Shuffle方式,会把每个ShuffleMapTask产生的文件数量最后合并为一个文件,而ShuffleReduceTask 只要在这个文件中拉去自取的那部分数据即可,产生的磁盘文件数量极大的减少。SortShuffle的框架和原理,我们在下一篇博客中会详细介绍。

Spark 1.1 版本中,引入SortShuffle ,经过实践应用后,在很多的应用场景下发现确实要比HashShuffle 的性能更好一些,因此在Spark 1.2 版本中,把默认的Shuffle方式从HashShuffle方式改为SortShuffle。在Spark 1.4 版本中,引入了Tungsten-SortShuffle,是SortShuffle的一种优化,也叫UnsafeShuffle,后面的博客也会详细详解。Spark 1.6 版本把Tungsten-SortShuffle并入了SortShuffle,让ShuffleManager自己去择优选择。到Spark 2.0版本后,HashShuffle从此就退出了历史舞台,一直延续到现在的Spark 2.4.0版本,使用的是SortShuffle(Sorted-Based Shuffle)基于排序的Shuffle。

3. Spark Shuffle 中数据结构 

在Spark 的Shuffle 中,有很多的数据存储结构,不同的结构对应着不同的功能。

3.1 AppendOnlyMap

AppendOnlyMap底层是由数组实现的,当需要对Key-Value进行聚合时,会使用AppendOnlyMap作为buffer。它是一个只支持追加的map,可以修改某个key对应的value, 但是不能删除已经存在的key。但是存储级别是Memory-Only ,shuffle reduce 数据不会溢写,在数据量不大的情况下可以,但是数据量大时,会极易出现OOM

3.2  ExternalAppendOnlyMap

继承于AppendOnlyMap ,但是存储级别是Memory and Disk,即在数据量达到一个阈值的时候,会把数据溢写到磁盘,达到释放内存空间,降低OOM的风险的作用。

3.3 PartitionedAppendOnlyMap

它的继承结构如上图所示,是SortShuffleWriter中用到的一种数据结构,在Map端需要聚合的时候,采用这种数据结构,这种结构也是一种Hash Table,能够根据Key,通过hash(Key),把数据插入到相应的位置。特性如下:

支持aggregation,重载了特质WritablePartitionedPairCollectioninsert方法,使其插入时,根据分区(partition, key)作为key重载了特SizeTrackingAppendOnlyMappartitionedDestructiveSortedIterator方法,在该方法中调用了AppendOnlyMapdestructiveSortedIterator对底层数组进行整理和排序后获得迭代据有可能不会连续存放。

3.4  PartitionedPairBuffer

 

底层实现和PartitionedAppendOnlyMap一样都是ArrayBuffer,主要用于SortShuffleWriter中Map 端不采用聚合和排序时使用。特性如下:

不支持aggregation,主要功能是插入值是有顺序的,主要起缓冲作用,只有顺序插入,没changeValue(聚合)update(更新)操数据连续存放在尾部。

3.5  MemoryPage

     

内存页,这种数据结构是在UnsafeShuffleWriter中用到的一种数据结构,其实内存页也是内存中的一个Block,Records 是用一个8字节的指针数组来表示,前24位表示分区的数量,即ShuffleReduce端的数量,中间13位表示Page 的数量,后面27位是限制Page 的大小,因此一个Page 的最大也就2^27=128M。每一条记录都是用这样的一个PackedRecordPointer 来表示,由于存储着Partition number也就是PartitionId, 因此数据排序可以按照PartitionId 进行排序,这也是UnsafeShuffleWriter对SortShuffleWriter 的优化,只对PartitionId进行排序。

 

袁彬  2018.11.26  上海

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值