MapReduce之全流程讲解

周末心情好,来理下整个MapReduce的工作流程,方便记忆和理解。

hadoop四大组件之一的MapReduce分布式计算系统,和HDFS-分布式存储系统,YARN-分布式操作系统(主要负责资源调度,相当于操作系统)三分天下,那么我们就将数据从HDFS输入到最后输出到HDFS来详细聊一聊Mapreduce的工作机制。


首先,上图。光说不上图都是耍流氓。数据的供给交给HDFS,资源的调配交给YARN,对数据进行鬼斧神工处理的部分就交给mapreduce了。mapreduce一般来说,可以细分为十大组件,分别为:TextInputFormat,LineRecorderReader, Mapper,shuffle(partition,sort,combiner),GroupComparator,Reducer,LineRecorderWriter,TextOutputFormat。首先我们对这是个组件做一个大概的解释:

MapReduce之全流程讲解

TextInputFormat和LineRecorderReader,输入组件,主要负责从HDFS读取数据,默认是一个文件一行一行的读取,获取的数据进入map进行处理。

LineRecorderWriter和TextOutputFormat,输出组件,主要负责接收reducer处理好的数据写入DHFS,一般有多少个reduceTask就会生成几个文件。

Mapper,mapreduce编程框架中业务逻辑编写的第一个组件。mapreduce默认接收到的数据,以每行字符的偏移量为key,\t分隔,之后的其他内容为value,一般读取数据进行处理的时候,都需要将value进行切割,放在相应类型的数组中进行处理。

Reducer,mapreduce编程框架中业务逻辑编写的最后一个组件--自定义输出除外。reducer接收到数据,是经过mapper处理,shuffle后,分区好了的数据。默认reducer会根据分区,key值自然排序将数据交给输出组件,方法调用为 context.wirte(key,value)。


Shuffle三大组件:

1、partitioner---分区组件。底层调用getPartition方法,通过计算key得hash值与reducetast个数的商,将不同key值得键值对划分到各个分区,可以有效的避免reduce阶段出现的数据倾斜和提高整体运行效率。

2、sort---排序组件,针对分区之后的数据,进行一个自然顺序排序。默认采用的排序算法有快速排序和递归排序。

3、combiner---局部合并组件。该组件用户不指定的话,是不存在的。主要的用途是用来减缓reduce阶段的压力。也可以根据用户自己的需求,进行特殊的合并。

GroupComparator---分组组件。通常处理业务逻辑的时候,会碰到既需要分组,又需要排序的情况,比如常见的求某些范围内的TopN的问题。这时,常常需要我们根据排序规则,自定义分组,否则当排序规则与分组规则发生冲突的时候,mapreduce程序会报错或者输出错误的数据。详细参考我的另一篇博文--mapreduce中分组排序的一些认识。


下面,我们以经典的单词计数程序为例,来说明下这十大组件是怎么协调工作的。

首先,mapreduce通过TextInoutFormat组件,调用LineRecordReader中的nextKeyValue方法,一行一行的读取数据,当nextKeyvalue的值返回false时,表示读取完毕。读取的数据,会一行行的传递给mapper,mapper收到数据-value,以及数据行的其实偏移量-key,提供一个map方法,供开发者进行业务逻辑的编写。在wordCount程序中,我们将获取的每一行数据单独提取出一个个的单词,以单词为key,计算单为1位值。交给shuffle阶段。--自定义输入格式请移步我的另外一篇博文--Mapreduce自定义输入输出组件的认识。

然后数据进入shuffle阶段。以上说的是一个maptask读取数据,处理的情况。通常情况下,是有多个maptask共同发生以上的行为,所有的maptask都会输出一堆的键值对,在shuffle阶段进行大洗牌。进入了shuffle阶段的键值对数据,默认情况下,按照默认规则分区,自然排序,将相同的key进行合并之后,输出到reduce阶段。在这里,大神们根据自己的需要,修改分区(个数,大小),指定排序(默认情况下是自然排序,并且是一定会执行),进行局部合并(降低网络数据传输)都可以为所欲为。在某些业务逻辑下,涉及到同时自定义分组和排序,就需要用户编写自己的GroupComparator。经过shuffle阶段洗牌之后的数据,每个分区的数据都已经排序好,相同key值的数据被分到同一个reducetask,进行进一步的合并处理。

进入到reducer阶段,通过reduce方法,一般是对接收到的键值对的value进行逻辑处理。当然这个阶段的key值也是可以根据需求进行处理的。之后数据进入通过context.wirte方法进入输出阶段。


最后,LineRecorderWriter和TextOutputFormat组件通过改写write方法,将数据输出到指定的位置,输出成指定的文件等。

因此,总体来说Mapreduce各个组件之间分工明确,各司其职。但是通过深刻的理解其内部的运行机制,又可以灵活的利用各个组件,根据自己的业务需要,随意的进行改写。各个组件之间的界线又变的模糊起来。真是学的越多,越对学习充满了敬畏。吾生也有涯,而知也无涯,学无止境吧!!!


图片来自超级大牛中琦2513!!!!