Hadoop日记Day14---MapReduce源代码回顾总结

一、回顾单词统计源码

  View Code

代码1.1

二、原理与代码解析

2.1 MapReduce的任务与原理

2.1.1 MapReduce的工作原理

  MapReduce的工作原理如下图2.1所示。

图 2.1

  在图中我们已看出,关于File有两种划分,一个是split分片一个是block,注意分片只是逻辑划分,并不是像划分block那样,将文件真是的划分为多个部分,他只是逻辑上的的划分,可以说是只是读取时候按分片来读取。关于分片的大小默认为块大小,为什么要这样呢?那因为MapReduce作业 处理的文件是存放在DataNode上的,而且文件在DataNode上是按block存放的,而不同的block可是存放在不同的DataNode上的,如果分片大小大于block块大小,那么说明一个块满足不 了该分片,那么就需要再读取一个block块,这样当这两个block块位于不同的DataNode上 时,就要通过网络访问另一个节点,这样就可能造成网络延迟影响Mapreduce的执行效率,所以一般分片大小会默认为block块大小。

  在分析一下该图,不难看出,每一个split都分配了一个MappperTask,每个MapperTask又有三个箭头,有三个不同的走向表示分了三个区,那就有三个ReducerTask,而最终的结果会分不同的痛的部分存放在DataNode目录中。我们也可以对比下面这张图来对比理解MapReduce的工作原理,如图2.2所示。

图 2.2

2.1.2 map()和reduce的任务

<1>map任务处理
  1) 读取输入文件内容,解析成key、value对。对输入文件的每一行,解析成key、value对。每一个键值对调用一次map函数。
  2) 写自己的逻辑,对输入的key、value处理,转换成新的key、value输出。
  3) 对输出的key、value进行分区
  4) 对不同分区的数据,按照key进行排序、分组。相同key的value放到一个集合中。
<2>reduce任务处理
  1) 对多个map任务的输出,按照不同的分区,通过网络copy到不同的reduce节点。
  2) 对多个map任务的输出进行合并、排序。写reduce函数自己的逻辑,对输入的key、value处理,转换成新的key、value输出。
  3) 把reduce的输出保存到文件中。

2.2源码任务的对比分析

  关于任务和源码的对应分析主要是针对map的第一项和第二项任务。第一项任务是:读取输入文件内容,解析成key、value对。对输入文件的每一行,解析成key、value对。每一个键值对调用一次map函数。第二项任务是:写自己的逻辑,对输入的key、value处理,转换成新的key、value输出。

2.2.1 第一项任务

  从上面代码1.1中,可以看出这项任务是由下面这段代码来完成,如代码2.1所示。

1 FileInputFormat.setInputPaths(job, INPUT_PATH);//1.1指定读取的文件位于哪里
2 job.setInputFormatClass(TextInputFormat.class);//指定如何对输入文件进行格式化,把输入文件每一行解析成键值对       

代码 2.1

  分析这段代码,可以知道,由代码中的TextInputFromat这个类主要是来完成分割的任务的,下面先来看一下该类的树结构,如下图2.1所示。

图 2.2

  从图中可知,TextInputFormat的继承的关系为,TextInputFormat--->FileInputformat--->InputFormat,那么看进入TextInputFormat类,看一下该类的注释,和其中的方法,如下代码2.2,2.3,注释中的@link表示后面跟的是一个连接,可以点击查看。

  View Code

代码 2.2

  View Code

代码 2.3


  从上面的代码中可以知道InputFormat是一个抽象类,两面有两个抽象方法getSplitcreateRecordReader,由于抽象类中只有方法的声明,并没有方法的实现,所以要分析该类的实现类FileInputFormat,在该实现类中,实现了他的父类InputFormat的getSplits()方法,查看该类的源码及注释如下代码2.4所示。

  View Code

 代码 2.4

  注意,分片FileinputSplit只是逻辑划分,并不是像划分block那样,将文件真是的划分为多个部分,他只是逻辑上的的划分,可以说是只是读取时候按分片来读取,分片InputSplit大小默认为块大小,为什么要这样呢?那因为MapReduce作业 处理的文件是存放在datanode上的,而且文件在DataNode上是按block存放的,如果分片大小大于block块大小,那么说明一个块满足不了该分片需要再读取一个block块,而不同的block可是存放在不同的DataNode上的,这样当这两个block块位于不同的DataNode上时,就要通过网络访问另一个节点,这样就可能造成网络延迟影响Mapre-duce的执行效率,所以一般分片大小会默认为block块大小。


   我们知道FileInputFormat实现了,inputFormat的 getSplits()的抽象方法,那么另一个抽象方法createRecordReader由谁来实现呢,我们看一下该类的两个实现类FileIn putFormatTextInputFormat这两个实现类的源码,看一发现createRecordReader是在TextInputFormat这个实现类中实现的,我们看一下该类的源码如下代码2.5所示。

  View Code

代码2.5

  我们再分析一下createRecordReader()方法的返回值,他的返回值类型为RecordReader,返回值是new LineRecordReader (),而他继承了RecordReader,我们先看一下RecordReader源码如代码2.6所示。

  View Code

代码 2.6

  从上面的代码中我们可以发现,RecordReader类是一个抽象类,其中的抽象方法initialize(),主要是用来将内容解析成键值对的,nextKeyValue() getCurrentKey() ,getCurrentValue() 主要是用来获取键值对的内容的,他们的使用方法如下面代码2.7所示。

1 while(xxx.nextKeyValue()){
2         key=xxx.getCurrenKey();
3         value=xxx.getCurrentValue();
4     }

 代码 2.7

    从RecordReader的类中回到 LineRecordReader类我们可以看到,该类对RecordReader类的三个抽象方法nextKeyValue(), getCurrentKey(),getCurrentValue()进行了实现,LineRecordReader类源码如代码2.8所示。

  View Code

代码 2.8

  通过以上对TextInputFormat的一系列分析,我们可以知道文件是如何分片的,分片是如何被解析成键值对的。那么这些键值对是如何被提交到Mapper上的呢?我们一步步分析,首先我们知道,分片是被createRecordReader()解析成键值对的,他的返回值是new LineRecordReader (),代表被解析成的键值对,那么我们就分析一下 LineRecordRe ader和Mapper的关系。好那么我们就看一下,Mapper的源码,如代码2.9所示

 

  View Code

 

代码 2.9

  我们分析一下这段代码,其中的getCurrentKey(),getCurrentValue(),nextKeyValue(),在RecordReader也见过,那么是不是他的呢?我们点击getCurrentKey(),然后进入到,MapContext类,看一下他的一段代码如代码2.10所示。

 

  View Code

 代码 2.10

  我们从上面的代码,发现Reader的类型就是RecordReader类型,我们又知道他的子类就是LineRecordReader我们这样就知道了他与Mapper之间的关系了。那么我们也就清楚了计算机在Mapper第一阶段所做的事如图2.4所示。

图 2.4

 


   与TextInputFormat相对应的是OutputFormat,他的继承关系结构如图2.3所示,关于对他们的分析,可依据前面对InputFormat的分析方法进行分析在这里不再分析。

图 2.3

  

2.2.2 第二项任务

  这项任务主要是由我们自己来做,通过对map()函数进行覆盖来实现我们的业务逻辑,这也是我们在MapReduce编程过程中的主要工作量。在单词统计的项目中,在未经map()函数处理时,初始键值对<K1,V1>中,键K1表示存储位置,V2表示某一行的内容。由于我们要统计单词的个数,为了便于实现我们的目的,所以我们的中间结果<K2,V2>,K2表示单词,V2用特定的值1来表示。然后在经过reduce函数处理,得到我们的最终结果。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值