hadoop2.x的三大核心:mapreduce 、hdfs以及yarn ,其中核心之一mapreduce,利用了分而治之的思想,Map(映射)和 Reduce(归约),分布式多处理然后进行汇总的思想,比如:清点扑克牌把里面的花色都分开,一个人清点那么可能耗时4分钟,如果利用mapreduce的思想,把扑克牌分成4份,每个人对自己的那一份进行清点,然后4个人都清点完成之后把各自的相同花色放一起进行汇总,那么这样可能只会耗时1分钟。这就是mapreduce的思想,其中每个人就相当于一个map,汇总就相当于是reduce,最开始的分牌就是patition分区(如果不均匀分配就相当于是数据倾斜),从map到reduce的过程就是shuffle。

下面就简单说说我理解的mapreduce执行流程

略过提交任务的流程以及yarn的相关过程,可以参考:

这里直接从map任务被执行说起。

1.当map任务开始执行的时候,会先根据用户设置的FileInputFormat去读取数据源,默认是TextFileInputFormat读取hdfs中的文件(当然mapreduce内部也提供了其他的实现类,比如读取数据库的等等),我们也可以自己定义一个FileInputFormat,继承FileInputFormat类就可以重写isSplitable和createRecordReader方法并在createRecordReader方法里面返回一个自定义的RecordReader实例就行(也是继承RecordReader类就行,需要重写里面的getCurrentKey、close、getCurrentValue、getProgress、initialize、nextKeyValue这几个方法可以参考:)

hadoop中提交作业流程 hadoop提交任务过程_java

2.当上面的处理完成后会进入到map方法,就以wordcount为例,这里map收到的参数为文件的一行例如数据是:“hello lijie hello word spark scala java java java”,然后对上面的一行进行split(” “)切分,然后用context.write输出(hello ,1)(lijie ,1)(hello ,1)(word ,1)(spark ,1)(scala ,1)(java,1)(java,1)(java,1)

3.上面的输出会先写到一个缓冲区里面(环形缓冲区,默认100M),当写入百分之80的时候会对里面的数据进行dump,dump的过程会对里面的数据先进行分区然后排序,如果有combiner会进行局部的combiner,之后写入运行map程序的那台服务器的本地磁盘中,如果map一直执行,那么会每满百分之80又会执行上面的过程直到map执行完成

hadoop中提交作业流程 hadoop提交任务过程_分布式_02

3.上面的步骤走完之后产生了很多小的文件,然后会触发mr的文件合并,把多个文件进行合并,合并过程中又会进行排序和局部的combiner,如果定义的是2个reduce,那么最后每个map端就会生产2个分区文件,并且文件里面的内容会已经排序且局部combiner(前提是设置了combiner)

hadoop中提交作业流程 hadoop提交任务过程_java_03

4.map任务执行完成之后,reduce会从map端下载对应的文件,并且又会对下载过来的文件进行合并且排序并且会调用GroupComparator 对象(用来自定义哪些是一组的,mr程序默认key相同为同一组,但是可以自己定义GroupComparator,这样不同的key也可以进入同一个reduce方法进行处理,详情见:)

hadoop中提交作业流程 hadoop提交任务过程_java_04

5.执行reduce方法,并且执行reduce的逻辑,执行完成之后就会调用FileOutputFormat,这个同FileInputFormat一样,同样可以自定义,也是继承FileOutPutFormat返回一个RecordWriter,这里就不过多介绍,默认是TextFileOutputFormat写入到hdfs里面

6.整个mapreduce的执行流程就完成了,如果FileOutputFormat和FileInputFormat是默认的话,那么数据流就是:HDFS -> 本地磁盘 ->HDFS,并且多次进行IO操作,所以mr的瓶颈在于他的IO操作,只适合进行离线计算