Hadoop系列(三)——心脏命脉 MapReduce 详解

最近花了一段时间去了解MapReduce 的工作原理:Map对数据集上的独立元素进行指定的操作,生成键值对形式中间结果;shuffle是MapReduce的心脏,对中间结果进行数据整合分区排序处理,有助于编写效率更高的mapreduce程序和hadoop调优;Reduce则对中间结果中相同“键”的所有“值”进行规约,以得到最终结果。自己画了一张流程图如下图,希望能对MapReduce感兴趣/想了解的同学有所帮助。 同时也希望有发现内容不正确或者有疑问的地方,望指明,一起探讨,学习,进步。

在这里插入图片描述

通俗易懂理解MapReduce

现实生活中,比如期末考试完了,那考卷由不同的老师批改,完成后如果想知道全年级最高分,那么可以这么做:

1)各个老师根据自己批改过的所有试卷分数整理出来(map):

=>(course,[score1,score2,...])

2)各个老师把最高分汇报给系主任(shuffle)

=>(courese, [highest_score1,highest_score2,...])

3)系主任统计最高分(reduce)

=>(courese, highest_score)

当然,如果要多门课程混在一起,系主任工作量太大,于是副主任也上(相当于2个reduce),则老师在汇报最高分的时候,相同课程要汇报给同一个人(相同key传输给同一个reduce),例如数学英语汇报给主任,政治汇报给副主任。

从上述的例子我们可以总结出以下结论:

MapReduce是一种分布式计算模型,用以进行大数据量的计算。它屏蔽了分布式计算框架细节,将计算抽象成map、shuffle和reduce三部分,Map负责将数据打散,进行脏数据处理和过滤;shuffle是对map处理数据的结果进行分区和排序过程聚集整合;Reduce负责对shuffle处理的数据结果进行最终的计算处理和聚集。

map、shuffle和reduce三部分的任务分工如下:

在这里插入图片描述

最上面的第一张图是比较全的描述出MapReduce的过程,下面用一张粗略的简图来描述map、shuffle和reduce三种的关系:
在这里插入图片描述

Input hdfs文件切割

第一张大图中Input hdfs文件切割的过程为①②③④步骤,整个过程是通过TextInputFormat(->RecordReader --> read())一次读一行,返回(key,value)结果。

在hadoop源码中TextInputFormat是继承InputFormat这个抽象父类的,TextInputFormat本质上就是java的String,hadoop对其及java基本类型(比如int–>IntWritable,…)进行了封装而已。那么InputFormat是什么?

InputFormat

hadoop InputFormat 源码:

public abstract class InputFormat<K, V> {
   
    public InputFormat() {
   
    }

    public abstract List<InputSplit> getSplits(JobContext var1) throws IOException, InterruptedException;

    public abstract RecordReader<K, V> createRecordReader(InputSplit var1, TaskAttemptContext var2) throws IOException, InterruptedException;
}

hadoop InputFormat有两大核心方法getSplits逻辑分片和createRecordReader创建读取记录。

getSplits文件切割

关于getSplits逻辑分片,实际上我们最常用的就是FileInputFormat中的文件切割方法(重写InputFormat的getSplits),源码如下:

if ((length != 0) && isSplitable(fs, path)) {
     
    long blockSize = file.getBlockSize();  
    long splitSize = computeSplitSize(goalSize, minSize, blockSize);  
    long bytesRemaining = length;  
      
    while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) {
     
        int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);  
        splits.add(new FileSplit(path, length-bytesRemaining, splitSize, blkLocations[blkIndex].getHosts()));  
        bytesRemaining -= splitSize;          
    }  
      
    if (bytesRemaining != 0) {
     
      
    splits.add(new FileSplit(path, length-bytesRemaining, bytesRemaining,  blkLocations[blkLocations.length-1].getHosts()));        }  
  
} else if(length!=0) {
     
  
    splits.add
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值