MR数据流向示意图
步骤 1
输入文件从HDFS流向Mapper节点。在一般情况下,map所需要的数据就存在本节点,这就是数据本地化计算的优势,但是往往集群中数据分布不均衡(1000台节点,数据冗余度是10,每个文件并不能均匀分布在每个节点上),而MR的计算槽位是均匀分布在节点上的(配置文件中指定的map和reduce数量),所以势必有些计算节点需要通过数据传输从别的节点获取计算数据。
步骤 2
Mapper输出到内存缓冲区。Mapper的计算结果并不是立即写入本地的文件系统,而是首先写入内存缓冲区,并且Partitioner也发生在这个阶段,就是map的计算结果写入到内存缓冲区的时候会进行Partitioner操作对输出键值对进行分区。
步骤 3
从内存缓冲区到本地磁盘。当内存缓冲区达到一定的阈值的时候就会将数据以临时文件的形式写入本地磁盘,这个过程称为spill,spill的是还会按照key的序列化字节做排序。当整个map任务结束的时候,会对这些临时文件以Partitioner为单位进行合并操作,对于同一个分区将进行多次合并,排序后生成一个大的Region文件。内存缓冲区的默认大小是100M,溢写比例默认是0.8(可以通过spill.percent参数来调节)。
如果用户作业设置了Combiner,那么spill之前会对map的输出键值对调用Combiner类做规约操作,这样可以降少写入到磁盘的数据量,从而进一步减少Shuffle阶段从Mapper到Reducer端的数据传输量。
步骤 4
从Mapper端的本地文件系统流入Reducer端。这也就是Reduce中的Shuffle阶段。这有分三种情况:第一种,对于多个Reduce的情况,需要将Mapper的Region文件远程复制到对应的Reduce节点(4-1)。第二种,Mapper所在的节点就有Reduce槽位(有reduce槽位就在本地执行reduce操作,因为本地化计算更快,并且reduce也是并行计算,在任何节点计算,结果都一样),则Mapper的输出Region文件会先写入本机Reduce的内存缓冲区(4-2)。第三种,本机的Reduce还会接收来自其他Mapper输出的分区Region文件(一个节点上可以有多个map,使用本机的一个reduce处理本机上多个map的输出)(4-3)。
步骤 5
从Reduce端的内存缓冲区流向Reduce端的本地磁盘。Reduce端的内存缓冲区也有阈值,当Region超过阈值时就会写入到Reduce端的本地文件系统。这个过程即使Reduce中的Merge和Sort阶段。Merge分为两种情况:内存文件合并(5-1)和磁盘文件合并(5-2),同时还会以key键进行排序,最终生成已经对相同key的value进行聚集并排过序的输出文件
步骤 6
Merge和Sort之后数据直接流向Reduce函数进行归约处理。
步骤 7
reduce完成之后根据用户指定的输出文件格式写入HDFS中,生成相应的part-*形式的文件。
参考
hadoop核心技术 p173-p174.