Hadoop -- MapReduce过程

2019-03-28 14:17|来源: 网络

我们对MapReduce作了大概了解( 见 http://www.linuxidc.com/Linux/2011-12/48897.htm ),知道它如何进行数据处理。今天我们走进MapReduce,分析MapReduce源代码,看看它到底是如何实现的,我们会根据数据流动的顺序来进行分析 :-)

1.读取数据(InputFormat)

读取数据由InputFormat类完成。InputFormat类的功能如下:

  • 验证作业的输入格式

  • 由InputSplit类将指定输入目录中的输入文件拆分成逻辑文件,即key/value序对,每个逻辑文件将被分配到一个Mapper中

  • 提供RecordReader实现类,从逻辑文件中搜集输入记录给Mapper类进行处理


InputFormat类定义了两个抽象方法:getSplits和createRecordReader,前者根据作业(job)的配置,将输入文件切片并返回一个 InputSplit类型的数组;后者为InputSplit实例对象生成一个RecordReader对象,在InputSplit对象使用前,MapReduce框架会先进行RecordReader的实例化操作。InputFormat类图如Figure1:


Hadoop -- MapReduce过程

 

Figure1:InputFormat类图




InputSplit类定义了两个抽象方法:getLength和getLocations,getLength方法获取分片的大小,因此能根据输入分片的大小进行排序;getLocations方法获取输入数据所在节点的名称。InputSplit类图如Figure2:


Hadoop -- MapReduce过程

Figure2:InputSplit类图




RecordReader类实现了Closeable接口,共6个抽象方法:initialize,nextKeyValue,getCurrentKey,getCurrentValue,getProgress和close。RecordReader类图如下:


Hadoop -- MapReduce过程
Figure3:RecordReader类图


  • initialize:调用RecordReader对象时进行实例化;

  • nextKeyValue:读取下一个key/value对,读取成功返回true;

  • getCurrentKey:获取当前key值,返回当前key值,如果没有key值返回null;

  • getCurrentValue:获取当前value,即记录。

  • getProgress:获取当前RecordReader处理数据的进度,返回数值为0.0~1.0

  • close:关闭RecordReader


RecordReader将输入数据切片并转换成key/value对,该key/value对作为Mapper的输入。一般情况下,输入文件分片后是一组连续的记录,最少有N个分片(N是输入文件数)。用户需要控制好分片数,因为分片的大小和数量对作业的运作性能影响很大。


在使用InputFormat类时,需要指定数据的输入格式。Hadoop Map-Reduce框架提供了大量输入格式可供选择,主要区别在于文本输入格式(textual input format)和二进制输入格式(binary input format),下面列出几个较常用的格式:

  • KeyValueTextInputFormat:每行一对key/value序对;

  • TextInputFormat:key值为行号,value为行的内容;

  • NLineInputFormat:与KeyValueTextInputFormat类似,不同点是NLineInputFormat根据输入文件的行数分片,KeyValueTextInputFormat根据输入文件字节数分片;

  • MultiFileInputFormat:一个抽象类,用户可以通过实现该类,将多个文件聚集到一个分片中;

  • SequenceFileInputFormat:输入文件为Hadoop序列文件,其中包含序列化的key/value对。


KeyValueTextInputFormat和SequenceFileInputFormat格式是最常用的输入格式。可使用如下格式进行设置:

首先定义一个JobConf类对象(当然该对象需要初始化):

JobConf conf;


然后通过conf调用setInputFormat设置输入数据的格式:

conf.setInputFormat(KeyValueTextInputFormat.class);

   

   最后设置输入目录的路径:

FileInputFormat.setInputPaths(conf,MapReduceConfig.getInputDirectionary() );


InputFormat类图可以看到,创建记录读取器时还需要TaskAttemptContext对象,获取分片时需要JobContext对象,它们分别是获取任务(Task)和作业(Job)的信息。因为每一个文件的分片对应于一个任务(task),而getSplits方法返回的是 InputSplit类数组,用于完成整个作业(job),因此调用getSplits方法需要提供job的配置信息。这两个类我们后面再进行详细分析。现在我们来总结一下读取数据需要做些什么:

  1. 指定输入文件的目录

  2. 指定一个类用于读取数据并将该数据转换成key/value对


   到此读取数据阶段完成,接下来进入Map阶段,我们拭目以待吧 :-)

相关问答

更多
  • 在各个slave(datanode)上面有会有Map和Reduce执行代码。 在Job提交时,会打包该job的配置文件类文件,jar文件等,拷 贝到各个datanode上面,做本地执行的。
  • 首先,一个job具体启动多少个map,是由你配置的inputformat来决定的。inputformat在分配任务之前会对输入进行切片。最终启动的map数目,就是切片的结果数目。具体来看 一、如果使用是自定义的inputformat,那么启动多少个map,是由你实现的public InputSplit[] getSplits(JobConf job, int numSplits)方法决定的,返回的切片有多少个就启动多少个map任务。 二、如果是使用系统系统的TextInputFormat(或FileInpu ...
  • 你参考下这个吧eclipse中开发Hadoop2.x的Map/Reduce项目汇总
  • 它们被分离出来,因为这两个包都代表2个不同的API。 org.apache.hadoop.mapred是旧的API, org.apache.hadoop.mapreduce是新的。 这样做是为了让程序员以更方便,更简单和复杂的方式编写MapReduce作业。 您可能会发现此演示文稿很有用,其中详细讨论了不同之处。 希望这回答你的问题。 They are separated out because both of these packages represent 2 different APIs. org.a ...
  • 本教程提到: 下载Hadoop-core-1.2.1.jar,用于编译和执行MapReduce程序。 访问以下链接http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-core/1.2.1下载jar。 所以在这里你可以找到不同版本的所有罐子 This tutorial mentions : Download Hadoop-core-1.2.1.jar, which is used to compile and execute the MapRe ...
  • 在Hadoop中,您处理输入拆分而不是块。 输入拆分是完整的数据集。 您希望避免一个映射器超过两个拆分的情况,因为这会降低性能并创建流量。 在文本世界中,假设您在block1中并且您有一个句子,例如“我是一个哈”,而block2继续“doop developer”,那么这会创建网络流量,因为我们始终必须在一个完整的节点上工作输入拆分和一些数据必须转移到另一个节点。 In Hadoop you work on input splits and not on blocks. An input split is ...
  • 您可以将LIMIT与任务规范一起使用。 但是,如果您必须一次又一次地执行此操作,那么更好的自动化解决方案是使用OOZIE(hadoop的工作流编辑器),可以在hive中为您的数据创建分区。 You can use LIMIT with task specification. However if you have to do it again and again then a better automated solution is to use OOZIE (work flow editor for ha ...
  • mapper的输出键和值类型应该是reducer的输入类型,因此在你的情况下,reducer必须继承自 Reducer setOutputKeyClass和setOutputValueClass设置作业输出的类型,即map和reduce。 如果要为映射器指定其他类型,则应使用方法setMapOutputKeyClass和setMapOutputValueClass 。 作为旁注,当您不希望输出中的真值时,为什么要从 ...
  • Mapper接口按以下顺序需要4个类型参数:Map输入键,Map输入值,Map输出键和Map输出值。 在您的情况下,由于您正在处理4个整数,其中3个构成您的值,1个是您的密钥,因此使用IntWritable作为Map输入键并且应该使用Text而错误。 此外,您在MapClass定义中指定的类型与传递给Map函数的类型不匹配。 鉴于您正在处理文本文件,您的MapClass应定义如下: public static class MapClass extends MapReduceBase implements M ...
  • MapReduce的作用可以称为“执行引擎”。 Pig作为一个系统正在将Pig Latin命令转换为一个或多个MR Jobs。 Pig本身没有能力运行它 - 它将这项工作委托给Hadoop。 我会在编译器和操作系统之间建立类比。 OS执行时编译器创建程序。 在这个比喻中,Pig是编译器,Hadoop是OS。 猪做的更多 - 它运行作业,监视它们等等。所以除了编译器之外,它可以被视为“shell”。 在我的理解中,从以下角度看,Pig不是100%编译器 - 它不会根据命令编译MR作业。 它传递有关应该对已存在 ...