SortShuffleWriter部分源码

SortShuffleWriter部分源码

spark1.6以后,取消了基于hash的shuffle,只剩下基于sort的shuffle。

现在只存在以下三种shuffle writer:

BypassMergeSortShuffleWriter

UnsafeShuffleWriter

SortShuffleWriter

其中,BypassMergeSortShuffleWriter实现带Hash风格的基于Sort的Shuffle机制,和已经废弃的HashShuffleWriter类似。这个shuffle writer将传入的record写入单独的文件,每个reduce partition对应一个文件,然后拼接这些文件汇总成一个单独的输出文件。这个输出文件按照partitionId分成多个region,reducer会根据partitionId来fetch对应的region数据。

当存在大量的reduce partition时,这个shuffle writer是低效率的,因为它会同时对每个partition都打开一个serializer和文件流。

因此,SortShuffleManager只在满足以下条件时选择这个shuffle writer:

不能指定ordering,即在partition内不能排序;

不能指定Aggregator,即不能进行map端的聚合;

parttition的数量要小于spark.shuffle.sort.bypassMergeThreshold指定的阈值;

在一般情况下(不进行map端聚合)会默认使用BypassMergeSortShuffleWriter;

通过调试代码发现:根据map端之前的rdd的原分区,注意这些分区可能位于不同节点上,对于每一个原分区都会生成一个对应的ShuffleMapTask,对应的executor执行runtask(),继而调用BypassMergeSortShuffleWriter.write函数

在这里插入图片描述

输入是该分区的所有key:value集合的iterator迭代器

在这里插入图片描述
在这里插入图片描述

简而言之,在write函数中对每个原分区的数据进行了哈希分区,分区id号分别对应不同哈希值:如partition1:(1,3,4)partition2:(2,4,6)然后按顺序落盘。

得到的文件名是"shuffle_" + shuffleId + “" + mapId + "” + reduceId格式,注意这个文件已经和reduceid绑定了。

最终每个原分区对应的maptask都会得到一个对应的data文件以及index文件,index记录着每个后分区的位置信息。函数执行完毕,会映射到mapStatus中,供reducetask调用一遍获取shufflemap任务的元数据信息。

打印信息:
在这里插入图片描述

虽然是在本机测试的,但是通过分析源码可以知道一个maptask对应一个node,最后的输出结果会存储在当前节点,不存在跨节点的可能,至少在分区的阶段。这也印证了shuffle跨节点拉取数据只有在reduce任务才会执行。Reduce任务去拉不同map任务结果的对应分区号里面的数据。

为了弄清楚写中间文件是被归在ShuffleMapStage还是ReduceStage进行了以下实验:

测试样例:wordcountdefault.scala
在这里插入图片描述

结合webui显示的DAG图可以发现,测试结果:
在这里插入图片描述
如下:stage0,1均有shufflewrite过程,但是stage2没有。说明shuffleWrite阶段时间包含在上一阶段的末尾。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值