为了账号安全,请及时绑定邮箱和手机立即绑定

Spark内核分析之Shuffle操作流程(非常重要)

标签:
Spark

    如题,我们来分析一下spark的shuffle操作原理;为什么说其非常重要,是因为shuffle操作是我们在Spark调优中非常重要的一环,对shuffle进行了优化,往往可以使得我们的spark程序运行效率有极大的提升。依照惯例,我们先来看一张图;

webp

普通shuffle流程图

上图是一个普通的Shuffle操作流程原理图,一个shuffle操作由三个RDD算子构成,分别是mapPartitionsRDD,ShuffleRDD,mapPartitionsRDD;如上图所示,

1.每个ShuffleMapTask都会为每个ResultTask创建一个Bucket缓存和一个对应的ShuffleBlockFile磁盘文件;2.每个ShuffleMapTask的输出相关信息封装成一个MapStatus发送到DAGScheduler的MapOutputTracker中去;

3.ResultTask开始拉取该任务所需要的数据,ResultTask通过向DAGScheduler的MapOutputTracker获取MapStatus的信息,从而知道自己需要的数据所在的位置,然后去相应的位置拉去数据到该任务所在节点的内存中,如果内存不够,会将部分数据写入磁盘,完成这系列的操作是由ShufflerRDD算子完成的;

4.然后ResultTask对拉取到的数据进行聚合操作,最后生成mapPartitionsRDD算子;

想想上面的这个Shuffler流程会有什么问题?

我们来做一个假设,如果有100个ShuffleMapTask,2个CPU Core,100个ResultTask,那么这个shuffler操作将产生10000个文件,如此多的文件对于Spark作业的性能就是一个灾难;针对这个问题当然有对应的优化策略,接着我们来看另外一张图;

webp

优化的Shuffler流程图

        通过优化的Shuffler操作如上图所示,假设有100个ShufflerMapTask,2CPU core,100个Resulttask,优化后产生的中间文件是200个,是优化之前的1/50;那么这是如何做到的,通过阅读源码可以知道,只要引入consolidation机制就可以实现了,其配置是通过在SparkConf中配置对应的参数即可实现;

        来简单分析一下:一个ShuffleMapTask将数据写入本地不变,但是当这一批ShuffleMapTask运行完成以后,下一批ShuffleMapTask开始运行(一批ShuffleMapTask是指,同一时间有两个Task并行执行,因为有两个CPU Core),它们产生的数据会直接写入上一批ShuffleMapTask产生的本地文件中;上图中左边的一组可以称为一组ShuffleGroup,每个文件中都存储了多个ShuffleMapTask的数据,每个ShuffleMapTask所产生的数据是一个segment,每个File中通过索引,偏移量来标记每部分数据来自不同的ShuffleMapTask。

下面我们来看看源码是如何实现的;

webp

ShuffleMapTask的runTask

1.首先通过Spark全局变量得到shuffleManager对象,并通过shuffleManager对象获得Write对象;

2.接着,通过rdd.iterator方法对属于自己的partition进行计算,最后会调用我们自己编写的RDD算子来计算partition;

3.接着Writer调用自己的write方法将RDD算子计算的结果写入缓存;

webp

HashShuffleWriter的write

1.判断aggregator为true,并且是否设置了map端的combine操作;若成立,则进行map端的数据合并(这里是一个spark优化点,在我之前关于spark优化系列文章中有写过);

2.对所有经过合并操作之后的数据遍历,根据每个元素获得对应的bucketId,然后将改元素写入对应的bucket缓存中;

这里我们来看看这个shuffle对象做了什么?

webp

FileShuffleBlockManager的forMapTask

1.首先创建出一个ShuffleWriterGroup对象;

2.接着判断Spark作业是否设置了consolidateShuffleFiles;如果设置其为true,首先得到一个fileGroup对象,然后使用shuffleId,mapId,BucketId来得到一个blockId,接着根据这个blockId写数据到磁盘的对象;相反,如果没有设置consolidateShuffleFiles为true,则直接为每个shuffleMapTask创建一个blockFile,然后得到一个写数据到磁盘的对象;

3.执行完这里后,接着调用write方法将数据写入内存缓冲bucket,然后再将数据写入磁盘;

写数据到这里就完成了,然后会将产生的数据位置等信息封装成一个MapStatus对象发送给DAGSchedule的MapOutputTracker中;接下来ResultTask开始读取数据;

webp

ShuffleRDD的compute

webp

HashShuffleReader的read


webp

BlockStoreShuffleFetcher的fetch

webp

BlockStoreShuffleFetcher的fetch

总结:到此shuffle的整个操作流程就分析完了,接下来会分析底层数据存储的核心组件BlockManager的工作原理,,欢迎关注。

如需转载,请注明:

本篇:Spark内核分析之Shuffle操作流程(非常重要)



作者:z小赵
链接:https://www.jianshu.com/p/f07b3654eeaa


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消