Shuffle概念
shuffle,是一种多对多的依赖关系,即每个Reduce Task从每个Map Task产生数的据中读取一片数据,极限情况下可能触发M*R个数据拷贝通道(M是Map Task数目,R是Reduce Task数目)。
Shuffle描述着数据从map task输出到reduce task输入的这段过程。shuffle是连接Map和Reduce之间的桥梁,Map的输出要到Reduce中必须经过shuffle这个环节,shuffle的性能高低直接影响了整个程序的性能和吞吐量。
因为在分布式情况下,reduce task需要跨节点去拉取其它节点上的map task结果。这一过程将会产生网络资源消耗和内存,磁盘IO的消耗。
通常shuffle分为两部分:
Map阶段的数据准备和Reduce阶段的数据拷贝处理。
一般将在map端的Shuffle称之为Shuffle Write;
在Reduce端的Shuffle称之为Shuffle Read。
Spark 的 Shuffle 过程与 MapReduce 的 Shuffle 过程有着诸多类似,一些概念可直接套用,例如,Shuffle 过程中,
提供数据的一端,被称作 Map 端,Map 端每个生成数据的任务称为 Mapper;对应的,
接收数据的一端,被称作 Reduce 端,Reduce 端每个拉取数据的任务称为 Reducer;
Shuffle 过程本质上都是将 Map 端获得的数据使用分区器进行划分,并将数据发送给对应的 Reducer 的过程。
为什么需要 Shuffle?
因为需要将具有某种共同特征的一类数据汇聚到一个节点上进行计算。
Shuffle分类
1、hashshuffle : 默认不排序,直接进行shuffle
2、sortshuffle :默认先进行排序。在shuffle
3、Tungsten(钨丝) shuffle : 在sortshuffle的基础上对内存进行了优化
Shuffle定义
与 MapReduce 的 Shuffle 类似,即在分区之间重新分配数据,将数据打乱重新汇聚到不同节点的过程。
还是以 WordCount 为例。如下图所示:
对一个分区上进行map和flatMap可以如同流水线一样只在同一台的机器上进行,不存在多个节点之间的数据移动,而 reduceByKey 这样的操作,需要将相同的 key 做聚合操作。
上图中 Stage1 中按 key 做 hash 分配三个分区做 reduce 操,对于 Stage2 中任意一个分区而言,其输入可能存在与上游 Stage1 中每一个分区中,因此需要从上游的每一个分区所在的机器上拉取数据,这个过程称为Shuffle。
Shuffle过程的核心方法
Spark Shuffle 分为 Write 和 Read 两个过程。在 Spark 中负责 shuffle 过程的执行、计算、处理的组件主要是 ShuffleManager,其是一个 trait,负责管理本地以及远程的 block 数据的 shuffle 操作。
所有方法如下图所示。
主要方法解释:
- registerShuffle:注册 ShuffleDependency(宽依赖),同时获取一个ShuffleHandle 并将其传递给任务。
- getWriter:返回 ShuffleWriter 用于 Shuffle Write 过程。对一个分区返回一个 ShuffleWriter,并由 executors 上的 ShuffleMapTask 任务调用。
- getReader:返回 ShuffleReader 用于 Shuffle Read 过程。
map端的Shuffle简述:
- input:根据split输入数据,运行map任务;
- patition: 每个map task都有一个内存缓冲区,存储着map的输出结果;
- spill:当缓冲区快满的时候需要将缓冲区的数据以临时文件的方式存放到磁盘;
- merge: 当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。
reduce端的Shuffle简述:
reduce task在执行之前的工作就是不断地拉取当前job里每个map task的最终结果,然后对从不同地方拉取过来的数据不断地做merge,也最终形成一个文件作为reduce task的输入文件。