MapReduce Shuffle过程分析

总体概述

MapReduce中的Shuffle更像是洗牌的逆过程,是将无规律的数据进行一定的规律化。下面是一张官方对shuffle描述的过程图。

1

在MapReuce的计算模型中,Map的输出是作为Reduce的输入,在Reduce进行处理之前还需要!通过Shuffle来进行前期的处理。Shuffle横跨了map端和reduce端,在map端包括了partition,collect,sort,spill,merge的过程;reduce端包括了copy和merge&sort的过程。

2

在Hadoop集群环境下,大部分的map task和reduce task的执行是在不同节点上的。而Reduce在执行处理时需要跨节点去拉取其位于不同节点上map task的结果。这样会导致在运行的多个job时会产生大量的网络资源开销,这是mapreduce调优的一个很大的关键。另外在节点内,反复的从磁盘上读写数据也造成了巨大的磁盘IO开销(因为map最终都会把结果写到磁盘上),所以我们希望Shuffle过程可以:
1. 完整地从map task端拉取数据到reduce端,保证数据的完整性;
2. 在跨节点拉取数据时,尽可能地减少带宽的不必要消耗;
3. 减少磁盘IO对task执行的影响。

可优化的地方是减少拉取数据的量,并尽量使用内存而不是磁盘。


Map端分析

Map端的shuffle过程包括分区partition、输出collect、排序sort、溢写spill、合并merge等过程。流程图如下:

3


Collect

Kubuffer是一个环形数据结构,以便最大化使用该内存空间。Kvbuffer中总共放置了两种数据,即k-v数据和索引数据(kvmeta),这两种不同的数据相邻但互不重叠,以一个临时的分界点equator进行区分,分界点在每次spill操作后都会更新。假设初始的equator为0,k-v数据是向上增长存储的,kvmeta数据是向下增长的,如图所示:

4

在内存缓冲区,kvbuffer的存放指针bufindex一直向上增长,索引是kv对在kvbuffer中的索引,是个四元组,包括:value的起始位置、key的起始位置、partition值、value的长度,占用四个Int长度,Kvmeta的存放指针kvindex每次都是向下跳四个“格子”,然后再向上一个格子一个格子地填充四元组的数据。


Sort

在spill之前,还有个SortAndSpill操作,sort先把Kvbuffer中的数据按照partition值和key两个关键字升序排序,移动的只是索引数据,排序结果是Kvmeta中数据按照partition为单位聚集在一起,最终结果是同一partition内的按照key有序排列。


Spill

关于Spill触发的条件,是通过设置阈值来进行触发的。在Spill线程进行SortAndSpill的同时,Map仍会一直输出数据。如果bufindex和Kvindex指针持续增长,那么必然会相碰,碰头之后再重新开始或者移动内存是非常麻烦的。所以,spill开始的同时,Map会取kvbuffer中剩余空间的中间位置设为新的分界点,bufindex和kvindex指针移动到这个分界点,然后两者继续按照既定的轨迹放置数据。分界点的转换如下图所示:

5

Map任务总要把输出的数据写到磁盘上,即使输出数据量很小在内存中全部能装得下,在最后也会把数据刷到磁盘上。(Spark中对此进行了优化)

Spill过程需根据排过序的kvmeta依次把每个partition里的kv数据写到“spill1.out”文件中,直到把所有partition遍历完。一个partition在磁盘文件中对应的数据也叫段(segment)。同时,会产生该spill文件对应的索引“spill1.out.index”用来直接获取某个partition在该文件中存放的起始位置。索引为一个三元组,记录一个partition对应的数据在该磁盘文件中的起始位置、原始数据长度、压缩后的数据长度。索引放在内存中,但如果内存放不下,则写入磁盘文件中。每一次Spill过程最少会生成一个out文件,有时还会生成index文件,Spill的次数也烙印在文件名中。索引文件和数据文件的对应关系如下图所示:

6


Merge

Map输出数据量如果很大的话,就可能会进行多次Spill,从而产生很多out文件和Index文件,并且分布在不同的磁盘上。如果对这些文件不加以处理的话会对后面reduce的copy过程造成很大的影响,此时就需要利用merge把这些输出和索引文件进行合并。

merge过程创建一个file.out文件和一个file.out.Index文件用来存储最终的输出和索引。merge是一个partition一个partition进行合并的。对于某个partition来说,从索引列表中查询这个partition对应的所有索引信息,每个对应一个段插入到段列表中。然后对这个partition对应的所有segment进行合并以形成一个segment。当这个partition对应多个segment时,会分批进行合并:先从segment列表中把第一批取出来,以key为关键字放置成最小堆,然后从最小堆中每次取出最小的

Reduce端分析


Copy

Reduce端copy数据的过程就是从map端拽取自己所需的输出结果。reduce任务通过HTTP向各个Map task所在的tasktracker拖取它所需要的数据。每个map节点都会启动一个常驻的HTTP server,其中一项服务就是响应Reduce来拖取Map数据。当有MapOutput的HTTP请求过来的时候,HTTP server就读取相应的Map输出文件中对应这个Reduce的数据,并通过网络流输出给Reduce。


Merge Sort

Copy过来的数据会先放入内存缓冲区中,这里的缓冲区大小要比map端的更为灵活,它基于JVM的heap size设置的。使用的缓存区大小默认是64K。有些Map的数据较小是可以放在内存中的,但如果在内存中不能放下这个Map数据,则直接把Map数据写到磁盘上,并在本地目录创建一个文件,从HTTP流中读取数据然后写到磁盘中。拖一个Map数据过来就会创建一个文件,当文件数量达到一定阈值时,开始启动磁盘文件merge,把这些文件合并输出到一个文件。

这样最后Reduce任务拖过来的数据有些放在内存中了有些放在磁盘上,最后会对这些来一个全局合并。这里使用的Merge和Map端使用的Merge过程一样。Map的输出数据已经是有序的,Merge进行一次合并排序,所谓Reduce端的sort过程就是指这个合并的过程。一般Reduce是一边copy一边sort,即copy和sort两个阶段是重叠而不是完全分开的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值