MapReduce框架原理
MapReduce工作流程
以下()中标号对应图中数字标号。
流程详解:
1. 文件读取过程:
(1) 待处理文本被提交给客户端。
(2) 在客户端submit数据之前,会获取待处理数据的信息,然后对任务数据进行切片,切片默认与切块大小一致,即每128M为一片。每一片对应一个map任务。
(3) 客户端提交切片信息。
(4) 进程MR appmaster会计算出所需要的资源和maptask(在NodeManager上运行)的数量,并向Yarn中的主节点ResourceManager申请。
2. Map业务逻辑过程:
(5) 待处理文本通过InputFormat流(默认TextInputFormat)中的RecorderReader方法读取。
(6) 在Maptask中,会将数据进行切分,形成<k,v>对形式,然后通过context.write进行输出。
3. shuffle过程
(7) 在(6)中输出的数据通过outputCollector输出到环形缓冲区。内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件(默认缓冲区大小默认100M,阈值是80%。当缓冲区内文件达到80%就会开始溢写,将这部分文件开始输出到磁盘,剩下20%继续写入文件)。(8)~(11)其实包含在(7)过程中。
(8) 在溢写到磁盘的过程中,会进行HashPatition分区(默认1个)、Key.compareTo排序(默认按字典顺序排序)和Combiner合并(可选,作用是进行预合并,减少reduce的压力,多个溢出文件会被合并成大的溢出文件),在溢出过程中,及合并的过程中,都要调用partitioner进行分区和针对key进行排序。
(9) 以图中(9)为例,得到3个溢写文件(每个溢写文件最大80M,因为阈值是80%),每个溢写文件被分为2个区。
(10) 对溢写文件进行归并排序(区和区合并)。
(11) 合并结束后,就都写入磁盘。
4. Reduce过程
(12) 所有maptask任务完成后,启动相应数量的reducetask,并且告知reducetask处理的数据范围(数据分区,几个分区就几个reducetask)。
(13) 每个reducetask获取自己的数据文件,然后合并文件,进行归并排序。
(14) 按组取数据,将value值合并(代码中reduce()执行过程)。
(15) 对(13)中的数据进行分组,即按key值分组。
(16) 通过输出流OutPutFormat(默认是TextOutPutFormat)中的RecordWriter进行输出(也是以<k,v>对的形式进行输出),每个分区(即每个reducetask)输出为一个文件part-r-xxx…。
5. 其他
Shuffle中的缓冲区大小会影响到mapreduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快。
缓冲区的大小可以通过参数调整,参数:io.sort.mb 默认100M。