mapreduce原理看来很多文章,就是没能很好地表述出来,还是需要自己写一下文章,独立思考一下整体思路才行啊。用自己的话来说话。
首先需要知道mapreduc任务是怎么启动的:
当客户的提交一个mapreduce任务,将产生一个job,Hadoop是将job分成task来进行处理的:map task和reduce task
Hadoop怎么控制job的运行呢?由两种节点来控制:JobTracker和TaskTracker。JobTracker协调整个job的运行,它还负责分配task到TaskTracker上;TaskTracker负责运行task,并将结果返回给JobTracker
接下来看看数据输入:
Hadoop会将输入数据分成固定的大小的 数据块(input split),并为每个数据块创建一个task,也就是说,task是运行数据块的。
上面说过,TaskTracker运行task,task运行数据块的,我们知道,数据是存放在DataNode上的,为了提高效率,Hadoop会让输入数据所在的DataNode跟task执行的DataNode是同一个的,不然就需要从DataNode n传送数据到DataNode m,效率低下。
总的来说,提交任务----数据输入----任务控制----完成job,下面为完整的job运行原理:
接下来,看看map过程和reduce过程,看看他们到底是怎么去处理数据的。
map过程:
读取input split中的一个个record,调用map函数,输出结果----结果不是直接写入磁盘的,而是先写到一个环形缓冲区中(一般100M,达到80M就溢出),达到一定的大小后才会写入硬盘,写入硬盘之前,会对数据进行hash,分到不同的分区(partition)中,partition的数目就是reduce的数目,会对分区中的数据按照key在内存中进行排序,然后溢出后都会flush数据,生成一个spill文件。在task结束前,会有产生很大spill文件,需要对这些文件进行合并(不断地排序和combia),最后合并成一个按分区排好序的大文件。为什么说combia能减少写入磁盘的数据量呢?多条数据,combia后的结果是[key, a1,a2,a3,a4...],这样确实减少了数据量。
reduce过程:
当map task完成后,通知TaskTracker,TaskTracker通知JobTracker
reduce task需要获取对应partition的map输出,当一个map task完成后,reduce task就开始进行数据的copy,不同的map task的完成时间是不同的,不需要等待。当很多map数据copy到reduce task后,一个背景线程就会将其合并为一个大的排好序的文件,当所有的map输出都copy到reduce task后,进入sort过程,最后将map输出合并为一个大的排好序的文件(如果整个过程中,map输出的数据很小,直接扔内存就行了)。最后的一次合并没有写硬盘了,而是直接输入到reduce函数,处理完后写入HDFS。