MapReduce工作流程
一.流程示意图
二.流程详解
1.split阶段
首先mapreducec会根据要运行的大文件来进行split,每个输入分片(input split)针对一个map任务,输入分片(InputSplit)存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组。输入分片(InputSplit)通常和HDFS的block(块)关系密切。加入我们设定HDFS的块的大小是128M,我们运行的大文件是128*10MB,MapReduce会分为10个MapTask,每个MapTask都尽可能运行在block(块)所在的DataNode上,体现了移动计算不移动数据的思想
2.map阶段
map阶段就是执行自己编写的Mapper类汇中的map函数,Map过程开始处理,MapTask会接收输入分片,通过不断的调用map方法对数据进行处理,处理完毕后,转换为新的<key,value>键值对输出.
3.Shuffle阶段
shuffle阶段主要负责将map端生成的数据传递给reduce端,因此shuffle分别在map端的过程和在reduce端的执行过程。
具体执行过程如下:
(1)MapTask收集map()方法的输出<key,value>对,放到内存缓冲区(环形环形缓冲区),其中环形缓冲区的大小默认是100MB;
(2)环形缓冲区到达一定阈值(环形缓冲区大小的80%)时,会将缓冲区中的数据溢出本地磁盘文件,这个过程会溢出多个文件
(3)多个溢写文件会被合并成大的溢写文件。
(4)在溢写过程中及合并的过程中,都要调用Partitioner进行分区和针对key进行归并排序sort。
(5)合成大文件后,map端shuffle的过程也就结束了,后面进入reduce端shuffle的过程。
(6)在Reduce端,shuffle主要分为复制map输出(copy),排序合并(merge sort)两个阶段
Reduce任务通过HTTP向各个Map任务拖取它所需要的数据。
Copy过来的数据会先放入内存缓冲区中,如果内存缓冲区中能放得下这次数据的话就把数据直接写到内存中,即内存到内存merge。Reduce要向每个Map拖取数据,在内存中每个Map对应一块数据,当内存缓存区中存储Map数据占用空间达到一定程度的时候,开始启动内存中merge,把内存中的数据merge输出到磁盘上一个文件中,即内存到磁盘merge
当属于该reducer的map端输出全部拷贝完成,则会在reducer上生成多个文件(如果拖取的所有map数据总量没有超过内存缓冲区,则数据就只存在于内存中),这时开始执行合并操作,即磁盘到磁盘merge
4.Reduce阶段
reduce从合并的文件中取出一个一个的键值对group,调用用户自定义的reduce方法(),生成最终的输出文件
5.注意
shuffle中的缓冲区大小会影响到MapReduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数就越少,执行速度就越快。
缓冲区的大小可以通过参数调整,参数:io.sort.mb 默认100M。
三.各个阶段的工作机制
InputFormat是个接口,FileInputFormat和DBInputFormat是InputFormat的实现类
-
FileInputFormat—文件类型—抽象类
-
DBInputFormat—数据库类型—具体实现类
FileInputFormat是一个抽象类,有很多实现类,默认的是TextInputFormat
1.InputFormat数据输入
InputFormat 的主要功能:是确定每一个 map 任务需要读取哪些数据以及如
何读取数据的问题
- 读哪些数据:每个map读取哪些数据有InputSplit(数据切片)决定;
- 如何读取数据:由RecordReader来决定
inputformat就有获取inputsplit和RecordReader的方法
inputformat接口源码
package org.apache.hadoop.mapred;
import java.io.IOException;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
@Public
@Stable
public interface InputFormat<K, V> {
InputSplit[] getSplits(JobConf var1, int var2) throws IOException;
RecordReader<K, V> getRecordReader(InputSplit var1, JobConf var2, Reporter var3) throws IOException;
}
1.1FileInputFormat抽象类
1.1.1FileInputFormat源码解析
实现步骤:
(1)找到输入数据存储的目录
(2)开始遍历处理(规划切片)目录下的每一个文件
(3)遍历第一个文件hello.txt
a).获取文件大小fs.sizeOf(hello.txt)
b).计算切片大小computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
c).默认情况下,切片大小=blocksize
d).开