Mapredcue原理详解
一、切片机制
可以看我之前写的Mapreduce源码分析(一):FileInputFormat切片机制,源码详解这篇文章,这里只讲流程,不分析代码了
主要是FileInputFormat类中的getSplits(JobContext job)方法来进行切片
- 你的数据存放的目录:/input/wc.txt
- 遍历你目录下的所有文件
- 遍历到第一个文件wc.txt
- 计算文件大小
long length = file.getLen();
- 判断文件是否是本地文件,如果是则给文件分块,如果是hdfs文件,那么直接获取保存文件的数据块信息,把各个数据块的信息存储到BlockLocation[]数组中
- 获取数据块大小
long blockSize = file.getBlockSize();
默认是128M - 计算切片大小:
computeSplitSize(blockSize, minSize, maxSize);
如果minSize和maxSize没有重新设置,那么切片大小就是数据块大小=128M - 开始切片,形成第一个切片:wc.txt–0:128M 第二个切片:wc.txt–1:128-256 第三个切片:wc.txt–2:256-300
- 将切片信息写到切片规划文件中
二、MapTask读取切片信息
有几个切片就有几个MapTask,每个MapTask分别读取各个切片的数据
10. 实际上MapTask通过LineRecordReader这个类取读取数据的,可以看我之前写的Mapreduce源码分析(二):MapTask及LineRecordReader读取文件的工作机制,源码详解来帮助理解<K,V>键值对从何而来
返回的<Key,Value>,Key代表偏移量,Value代表一行的数据,如下图
11. 传入Mapper重写的map方法中,经过逻辑处理 形成新的<Key,Value>键值对,以WordCount单词计数来分析,新生成的<k,v>键值对,key保存的是一个单词,value为1表示出现了一次,通过context.write方法输出到OutputCollector中
12. OutputCollector把收集的<k,v>键值对写入到环形缓冲区中
三、环形缓冲区
环形缓冲区:是内存中构造的一个环形数据结构,其实就是一个环形数组,一般为100M
13. 到存储到数据达到环形缓冲区的80%时,会发生溢出
14. 在溢出数据之前会对数据进行分区和排序
分区:根据partition来进行分区,那么partition怎么来的呢?
在HashPartitioner这个类中有个getPartition的方法,其中numReduceTasks就是分区数,可以在Driver那设置,有几个numReduceTasks就有几个reduce输出文件
partition = (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
public int getPartition(K key, V value,
int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}
排序:然后把环形缓冲区中的数据根据partition值进行快速排序(升序),partition值相同的<k,v>为同一个区,
相同的partition会根据key的ASCII码值排序(升序)
【注】如果实体类实现了WritableComparable接口,重写了compareTo方法,key就要用key.compareTo方法对对象进行排序
四、对各个小文件进行归并排序
- 将环形缓冲区中排序后的内存数据不断溢出到本地磁盘中,如果map阶段处理的数据较大,可能会溢出多个文件
- 多个一处文件会merge合并成一个大的溢出文件,合并采用给归并排序,所以MapTask最终结果还是分区且区内有序的
五、 ReduceTask
- ReduceTask根据自己的分区号,区各个MapTask节点上拷贝相同partition的数据到ReduceTask本地磁盘工作目录
- ReduceTask会把同一分区的来自不同 MapTask的结果文件 ,在进行merge合并一个大文件(归并排序),大文件内按照key排序
- 合并成一个大文件后,根据key分组,调用GroupingComparator,把key相同的放一组,value进行迭代,从文件中每次取出一组<k,v>数据,key是分组的key,value是所有相同key的value的迭代
如:(“hadoop”,(1,1,1,1,1)),然后调用Reducer中重写的redcue方法进行逻辑处理 - 最后通过OutputFormat方法将结果数据写reduce各自的分区文件中
六、总结
- 除了环形缓冲区里了数据是放在内存中的,后面的数据包括溢出的和归并的都放在磁盘中
- shuffle过程:一个reduce拷贝每个map节点相同partition的数据到ReduceTask本地磁盘工作目录
- map输出是什么类型,reduce就要用什么类型接收
- 当map中处理的数据较多时,环形缓冲区会溢出很多个文件,可以调用combiner组件,逻辑和reduce一样,,合并相同的key,value迭代这样传效率高,不用传好多的key。
大致流程图如下: