• 链接多个MapReduce作业
  • 执行多个数据集的联结
  • 生成Bloom filter
 
1、链接MapReduce作业
 
[顺序链接MapReduce作业]
 
mapreduce-1 | mapreduce-2 | mapreduce-3 | ...
 
[具有复杂依赖的MapReduce链接]
 
     有时,在复杂数据处理任务中的子任务并不是按顺序运行的,因此它们的MapReduce作业不能按线性方式链接。例如,mapreduce1处理一个数据集,mapreduce2独立处理另一个数据集,而第3个作业mapreduce3,对前两个作业的输出结果做内部联结。
 
     Hadoop有一种简化机制,通过Job和JobControl类来管理这种(非线性)作业之间的依赖。Job对象是MapReduce作业的表现形式。Job对象的实例化可通过传递一个JobConf对象到作业的构造函数中来实现。除了要保持作业的配置信息外,Job还通过设定addDependingJob()方法维护作业的依赖关系。对于Job对象x和y,x.addDependingJob(y)意味着x在y完成之前不会启动。鉴于Job对象存储着配置和依赖信息,JobControl对象会负责管理并监视作业的执行。通过addJob()方法,你可以为JobControl对象添加作业。当所有作业和依赖关系添加完成后,调用JobControl的run()方法,生成一个线程来提交作业并监视其执行。JobControl有诸如allFinished()和getFailedJobs()这样的方法来跟踪批处理中各个作业的执行。
 
[预处理和后处理阶段的链接]
 
     Hadoop在版本0.19.0中引入了ChainMapper和ChainReducer类来简化预处理和后处理的构成。作业按序执行多个mapper来预处理数据,并在reducer之后可选地按序执行多个mapper来做数据的后处理。这一机制的优点在于可以将预处理和后处理步骤写为标准的mapper,逐个运行它们,可以在ChainMapper和ChainReducer中调用addMapper()方法来分别组合预处理和后处理的步骤。全部预处理和后处理步骤在单一的作业中运行,不会生成中间文件,这大大减少了I/O操作。
 
     例如,有4个mapper(Map1,Map2,Map3和Map4)和一个reducer(Reduce),它们被链接为单个MapReduce作业,顺序如下:Map1 | Map2 | Reduce | Map3 | Map4
 
     这个组合中,可以把Map2和Reduce视为MapReduce作业的核心,在mapper和reducer之间使用标准的分区和洗牌。可以把Map1视为前处理步骤,而Map3和Map4作为后处理步骤。我们可以使用driver设定这个mapper和reducer序列的构成:
 

代码清单 用于链接MapReduce作业中mapper的driver
 
  1. Configuration conf = getConf();
  2. JobConf job = new JobConf(conf);
  3.  
  4. job.setJobName("ChainJob");
  5. job.setInputFormat(TextInputFormat.class);
  6. job.setOutputFormat(TextOutputFormat.class);
  7.  
  8. FileInputFormat.setInputPaths(job, in);
  9. FileOutputFormat.setOutputPath(job, out);
  10.  
  11. JobConf map1Conf = new JobConf(false);
  12. ChainMapper.addMapper(job,
  13. Map1.class,
  14. LongWritable.class,
  15. Text.class,
  16. Text.class,
  17. Text.class,
  18. true,
  19. map1Conf);
  20.  
  21. JobConf map2Conf = new JobConf(false);
  22. ChainMapper.addMapper(job,
  23. Map2.class,
  24. Text.class,
  25. Text.class,
  26. LongWritable.class,
  27. Text.class,
  28. true,
  29. map2Conf);
  30.  
  31. JobConf reduceConf = new JobConf(false);
  32. ChainReducer.setReducer(job,
  33. Reduce.class,
  34. LongWritable.class,
  35. Text.class,
  36. Text.class,
  37. Text.class,
  38. true,
  39. reduceConf);
  40.  
  41. JobConf map3Conf = new JobConf(false);
  42. ChainReducer.addMapper(job,
  43. Map3.class,
  44. Text.class,
  45. Text.class,
  46. LongWritable.class,
  47. Text.class,
  48. true,
  49. map3Conf);
  50.  
  51. JobConf map4Conf = new JobConf(false);
  52. ChainReducer.addMapper(job,
  53. Map4.class,
  54. LongWritable.class,
  55. Text.class,
  56. LongWritable.class,
  57. Text.class,
  58. true,
  59. map4Conf);
  60.  
  61. JobClient.runJob(job);
 

 
     driver首选会设置全局的JobConf对象,包含作业名、输入路径及输出路径等。它一次性添加这个由5个步骤链接在一起的作业,以步骤执行先后为序。它用ChainMapper.addMapper()添加位于Reduce之前的所有步骤。用静态的ChainReducer.setReducer()方法设置reducer。再用ChainReducer.addMapper()方法添加后续的步骤。全局JobConf对象经历所有的5个add*方法。此外,每个mapper和reducer都有一个本地JobConf对象(map1Conf、map2Conf、map3Conf、map4Conf和reduceConf),其优先级在配置各自mapper/reducer时高于全局的对象。建议本地JobConf对象采用一个新的JobConf对象,且在初始化时不设默认值——new JobConf(false)。
 
     让我们通过ChainMapper.addMapper()方法的签名来详细了解如何一步步地链接作业,其中ChainReducer.setReducer()的签名和功能与ChainReducer.addMapper()类似:
 
public static <k1, v1, k2, v2> void
                                  addMapper(JobConf job,
                                                      Class <? extends Mapper<k1, v1, k2, v2>> class,
                                                      Class <? extends k1> inputKeyClass,
                                                      Class <? extends v1> inputValueClass,
                                                      Class <? extends k2> outputKeyClass,
                                                      Class <? extends v2> outputValueClass,
                                                     boolean byValue,
                                                     JobConf mapperConf)
 
     该方法有8个参数,第一个和最后一个分别为全局和本地的JobConf对象。第二个参数klass是Mapper类,负责数据处理。对于byValue这个参数,如果确信map1的map()方法在调用OutoutCollector.collect(K k, V v)之后不再使用k和v的内容,或者map2并不改变k和v在其上的输入值,则可以通过设定buValue为false来获取一定的性能提升;如果对Mapper的内部代码不太了解,则可以通过设定byValue为true,确保Mapper会按预期的方式工作。余下的4个参数inputKeyClass、inputValueClass、outputKeyClass和outputValueClass是这个Mapper类中输入/输出类的类型。
 
2、联结不同来源数据
 
[Reduce侧的联结]
 
 
  1. 首先mapper接收的数据来自两个文件,Customers及Orders;
  2. 在map()封装输入的每个记录后,就执行MapReduce标准的分区、洗牌和排序操作;
  3. reduce()函数接收输入数据,并对其值进行完全交叉乘积;
  4. 交叉乘积得到的每个合并结果被送入函数conbine()。
 
     Hadoop有一个名为datajoin的contrib软件包,在hadoop中它是一个用作数据联结的通用框架,它的jar文件位于contrib/datajoin/hadoop-*-datajoin.jar。hadoop的datajoin软件包有3个可供继承和具体化的抽象类:DataJoinMapperBase、DataJoinReducerBase和TaggedMapOutput。顾名思义,MapClass会扩展DataJoinMapperBase,而Reduce类会扩展DataJoinReducerBase。Datajoin软件包已经分别在这些基类上实现了map()和reduce方法,可用于执行联结数据流。
 

代码清单 来自两个reduce侧连接数据的内联结
 
  1. import java.io.DataInput;
  2. import java.io.DataOutput;
  3. import java.io.IOException;
  4. import java.util.Iterator;
  5.  
  6. import org.apache.hadoop.conf.Configuration;
  7. import org.apache.hadoop.conf.Configured;
  8. import org.apache.hadoop.fs.Path;
  9. import org.apache.hadoop.io.Text;
  10. import org.apache.hadoop.io.Writable;
  11. import org.apache.hadoop.mapred.FileInputFormat;
  12. import org.apache.hadoop.mapred.FileOutputFormat;
  13. import org.apache.hadoop.mapred.JobClient;
  14. import org.apache.hadoop.mapred.JobConf;
  15. import org.apache.hadoop.mapred.KeyValueTextInputFormat;
  16. import org.apache.hadoop.mapred.MapReduceBase;
  17. import org.apache.hadoop.mapred.Mapper;
  18. import org.apache.hadoop.mapred.OutputCollector;
  19. import org.apache.hadoop.mapred.Reducer;
  20. import org.apache.hadoop.mapred.Reporter;
  21. import org.apache.hadoop.mapred.TextInputFormat;
  22. import org.apache.hadoop.mapred.TextOutputFormat;
  23. import org.apache.hadoop.util.Tool;
  24. import org.apache.hadoop.util.ToolRunner;
  25.  
  26. import org.apache.hadoop.contrib.utils.join.DataJoinMapperBase;
  27. import org.apache.hadoop.contrib.utils.join.DataJoinReducerBase;
  28. import org.apache.hadoop.contrib.utils.join.TaggedMapOutput;
  29.  
  30. public class DataJoin extends Configured implements Tool {
  31.  
  32. public static class MapClass extends DataJoinMapperBase {
  33.  
  34. protected Text generateInputTag(String inputFile) {
  35. String datasource = inputFile.split("-")[0];
  36. return new Text(datasource);
  37. }
  38.  
  39. protected Text generateGroupKey(TaggedMapOutput aRecord) {
  40. String line = ((Text) aRecord.getData()).toString();
  41. String[] tokens = line.split(",");
  42. String groupKey = tokens[0];
  43. return new Text(groupKey);
  44. }
  45.  
  46. protected TaggedMapOutput generateTaggedMapOutput(Object value) {
  47. TaggedWritable retv = new TaggedWritable((Text) value);
  48. retv.setTag(this.inputTag);
  49. return retv;
  50. }
  51. }
  52.  
  53. public static class Reduce extends DataJoinReducerBase {
  54.  
  55. protected TaggedMapOutput combine(Object[] tags, Object[] values) {
  56. if (tags.length < 2) return null;
  57. String joinedStr = "";
  58. for (int i=0; i<values.length; i++) {
  59. if (i > 0) joinedStr += ",";
  60. TaggedWritable tw = (TaggedWritable) values[i];
  61. String line = ((Text) tw.getData()).toString();
  62. String[] tokens = line.split(",", 2);
  63. joinedStr += tokens[1];
  64. }
  65. TaggedWritable retv = new TaggedWritable(new Text(joinedStr));
  66. retv.setTag((Text) tags[0]);
  67. return retv;
  68. }
  69. }
  70.  
  71. public static class TaggedWritable extends TaggedMapOutput {
  72.  
  73. private Writable data;
  74.  
  75. public TaggedWritable(Writable data) {
  76. this.tag = new Text("");
  77. this.data = data;
  78. }
  79.  
  80. public Writable getData() {
  81. return data;
  82. }
  83.  
  84. public void write(DataOutput out) throws IOException {
  85. this.tag.write(out);
  86. this.data.write(out);
  87. }
  88.  
  89. public void readFields(DataInput in) throws IOException {
  90. this.tag.readFields(in);
  91. this.data.readFields(in);
  92. }
  93. }
  94.  
  95. public int run(String[] args) throws Exception {
  96. Configuration conf = getConf();
  97.  
  98. JobConf job = new JobConf(conf, DataJoin.class);
  99.  
  100. Path in = new Path(args[0]);
  101. Path out = new Path(args[1]);
  102. FileInputFormat.setInputPaths(job, in);
  103. FileOutputFormat.setOutputPath(job, out);
  104.  
  105. job.setJobName("DataJoin");
  106. job.setMapperClass(MapClass.class);
  107. job.setReducerClass(Reduce.class);
  108.  
  109. job.setInputFormat(TextInputFormat.class);
  110. job.setOutputFormat(TextOutputFormat.class);
  111. job.setOutputKeyClass(Text.class);
  112. job.setOutputValueClass(TaggedWritable.class);
  113. job.set("mapred.textoutputformat.separator", ",");
  114.  
  115. JobClient.runJob(job);
  116. return 0;
  117. }
  118.  
  119. public static void main(String[] args) throws Exception {
  120. int res = ToolRunner.run(new Configuration(),
  121. new DataJoin(),
  122. args);
  123.  
  124. System.exit(res);
  125. }
  126. }
 

 
 
 [转载请注明] http://www.cnblogs.com/zhengrunjian/  
 
 
 
 
 

[Hadoop in Action] 第5章 高阶MapReduce的更多相关文章

  1. [Hadoop in Action] 第7章 细则手册

    向任务传递定制参数 获取任务待定的信息 生成多个输出 与关系数据库交互 让输出做全局排序   1.向任务传递作业定制的参数        在编写Mapper和Reducer时,通常会想让一些地方可以配 ...

  2. [Hadoop in Action] 第6章 编程实践

    Hadoop程序开发的独门绝技 在本地,伪分布和全分布模式下调试程序 程序输出的完整性检查和回归测试 日志和监控 性能调优   1.开发MapReduce程序   [本地模式]        本地模式 ...

  3. [Hadoop in Action] 第4章 编写MapReduce基础程序

    基于hadoop的专利数据处理示例 MapReduce程序框架 用于计数统计的MapReduce基础程序 支持用脚本语言编写MapReduce程序的hadoop流式API 用于提升性能的Combine ...

  4. [hadoop in Action] 第3章 Hadoop组件

    管理HDFS中的文件 分析MapReduce框架中的组件 读写输入输出数据   1.HDFS文件操作   [命令行方式]   Hadoop的文件命令采取的形式为: hadoop fs -cmd < ...

  5. [Hadoop in Action] 第2章 初识Hadoop

    Hadoop的结构组成 安装Hadoop及其3种工作模式:单机.伪分布和全分布 用于监控Hadoop安装的Web工具   1.Hadoop的构造模块   (1)NameNode(名字节点)       ...

  6. [Hadoop in Action] 第1章 Hadoop简介

    编写可扩展.分布式的数据密集型程序和基础知识 理解Hadoop和MapReduce 编写和运行一个基本的MapReduce程序   1.什么是Hadoop   Hadoop是一个开源的框架,可编写和运 ...

  7. Cloudera Hadoop 5& Hadoop高阶管理及调优课程(CDH5,Hadoop2.0,HA,安全,管理,调优)

    1.课程环境 本课程涉及的技术产品及相关版本: 技术 版本 Linux CentOS 6.5 Java 1.7 Hadoop2.0 2.6.0 Hadoop1.0 1.2.1 Zookeeper 3. ...

  8. 《JavaScript设计模式与开发实践》——第3章 闭包和高阶函数

    闭包 变量的作用域和生存周期密切相关 高阶函数 函数可以作为参数被传递 函数可以作为返回值输出

  9. Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

    在上面一个章节中,详细的讲解了Kotlin中关于Lambda表达式的语法以及运用,如果还您对其还不甚理解,请参见Kotlin--高级篇(一):Lambda表达式详解.在这篇文章中,多次提到了Kotli ...

随机推荐

  1. StringMVC 中如何做数据校验

    步骤一:引入四个jar包 步骤二:注册类型转换器 <context:component-scan base-package="cn.happy.controller"> ...

  2. 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?

    今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制层的技术框架由struts2迁移到springMVC,我突然有了一个新的疑 ...

  3. 参考bootstrap中的popover.js的css画消息弹框

    前段时间小颖的大学同学给小颖发了一张截图,图片类似下面这张图: 小颖当时大概的给她说了下,其实小颖也不知道上面那个三角形怎么画嘻嘻,给她说了DOM结构,具体的css让她自己百度,今天小颖自己参考boo ...

  4. mysql 7下载安装及问题解决

    mysql 7安装及问题解决 一.mysql下载 下载地址:https://www.mysql.com/downloads/ Community (GPL) Downloads MySQL Commu ...

  5. ASP.NET Core project.json imports 是什么意思?

    示例代码: "frameworks": { "netcoreapp1.0.0": { "imports" : "portable- ...

  6. Autofac - 生命周期

    实例生命周期决定在同一个服务的每个请求的实例是如何共享的. 当请求一个服务的时候,Autofac会返回一个单例 (single instance作用域), 一个新的对象 (per lifetime作用 ...

  7. HTML5笔记2——HTML5音/视频标签详解

    音视频的发展史 早期:<embed>+<object>+文件 问题:不是所有浏览器都支持,而且embed不是标准. 现状:Realplay.window media.Quick ...

  8. Win10提示没有权限使用网络资源问题解决

    借鉴链接:http://www.cr173.com/html/67361_1.html Win10提示没有权限使用网络资源解决方法 1.打开控制面板; 2.在所有控制面板项中找到凭据管理器; 3.添加 ...

  9. iOS系列教程 目录 (持续更新...)

      前言: 听说搞iOS的都是高富帅,身边妹子无数.咱也来玩玩.哈哈. 本篇所有内容使用的是XCode工具.Swift语言进行开发. 我现在也是学习阶段,每一篇内容都是经过自己实际编写完一遍之后,发现 ...

  10. hive

    Hive Documentation https://cwiki.apache.org/confluence/display/Hive/Home 2016-12-22  14:52:41 ANTLR  ...