学习 hadoop,必不可少的就是编写 MapReduce 程序。当然,对于简单的分析程序,我们只需一个 MapReduce 任务就能搞定,然而对于比较复杂的分析程序,我们可能需要多个Job或者多个Map或者Reduce进行分析计算。 本课程我们主要学习多个 Job 或者多个 MapReduce 的编程形式。

MapReduce 的主要有以下几种编程形式。

迭代式 MapReduce

MapReduce 迭代方式,通常是将上一个 MapReduce 任务的输出作为下一个 MapReduce 任务的输入,可只保留 MapReduce 任务的最终结果,中间数据可以删除或保留,可根据业务需要自行决定。   迭代式 MapReduce 的示例代码如下所示。

Configuration conf = new Configuration();

//第一个 MapReduce 任务
Job job1 = new Job(conf,"job1");
.....
FileInputFormat.addInputPath(job1,input);//job1的输入
FileOutputFromat.setOutputPath(job1,out1);//job1的输出
job1.waitForCompletion(true); //第二个 Mapreduce 任务
Job job2 = new Job(conf,"job2");
.....
FileInputFormat.addInputPath(job2,out1);//job1的输出作为job2的输入
FileOutputFromat.setOutputPath(job2,out2);//job2 的输出
job2.waitForCompletion(true); //第三个 Mapreduce 任务
Job job3 = new Job(conf,"job3");
.....
FileInputFormat.addInputPath(job3,out2);//job2的输出作为job3的输入
FileOutputFromat.setOutputPath(job3,out3);//job3 的输出
job3.waitForCompletion(true);
.....

虽然 MapReduce 的迭代可实现多任务的执行,但是它具有如下两个缺点:

1、每次迭代,如果所有 Job 对象重复创建,代价将非常高。

2、每次迭代,数据都要写入本地,然后从本地读取,I/O和网络传输的代价比较大。

依赖关系式 MapReuce

依赖关系式 MapReduce主要是由 org.apache.hadoop.mapred.jobcontrol 包中的 JobControl 类来实现。JobControl 的实例表示一个作业的运行图, 你可以加入作业配置,然后告知 JobControl 实例作业之间的依赖关系。在一个线程中运行 JobControl 时,它将按照依赖顺序来执行这些作业。也可以查看进程, 在作业结束后,可以查询作业的所有状态和每个失败相关的错误信息。如果一个作业失败,JobControl 将不执行与之有依赖关系的后续作业。

依赖关系式 MapReuce 的示例代码如下所示。

Configuration conf1 = new Configuration();
Job job1 = new Job(conf1,"Job1");
.........//job1 其它设置 Configuration conf2 = new Configuration();
Job job2 = new Job(conf2,"Job2");
.........//job2 其它设置 Configuration conf3 = new Configuration();
Job job3 = new Job(conf3,"Job3");
.........//job3 其它设置 ControlledJob cJob1 = new ControlledJob(conf1);//构造一个 Job
cJob1.setJob(job1);//设置 MapReduce job
ControlledJob cJob2 = new ControlledJob(conf2);
cJob2.setJob(job2);
ControlledJob cJob3 = new ControlledJob(conf3);
cJob3.setJob(job3); cJob3.addDependingJob(cJob1);//设置job3和job1的依赖关系
cJob3.addDependingJob(cJob2);//设置job3和job2的依赖关系 JobControl JC = new JobControl("123");
//把三个构造的job加入到JobControl中
JC.addJob(cJob1);
JC.addJob(cJob2);
JC.addJob(cJob3);
Thread t = new Thread(JC);
t.start();
while (true) {
if (jobControl.allFinished()) {
jobControl.stop();
break;
}
}

注意:hadoop的JobControl类实现了线程Runnable接口。我们需要实例化一个线程来启动它。直接调用JobControl的run()方法,线程将无法结束。

线性链式 MapReduce

大量的数据处理任务涉及对记录的预处理和后处理。

例如:在处理信息检索的文档时,可能一步是移除 stop words(像a、the和is这样经常出现但不太有意义的词),另一步做stemming(转换一个词的不同形式为相同的形式,例如转换finishing和finished为finish)。

你可以为预处理与后处理步骤各自编写一个 MapReduce 作业,并把它们链接起来。在这些步骤中可以使用IdentityReducer(或完全不同的 Reducer)。 由于过程中每一个步骤的中间结果都需要占用I/O和存储资源,这种做法是低效的。另一种方法是自己写 mapper去预先调用所有的预处理步骤,再让reducer调用所有的后处理步骤。这将强制你采用模块化和可组合的方式来构建预处理和后处理。因此Hadoop引入了ChainMapper 和ChainReducer类来简化预处理和后处理的构成。

hadoop提供了专门的链式ChainMapper和ChainReducer来处理线性链式MapReduce任务。在Map或者Reduce阶段存在多个Mapper,这些Mapper像Linux管道一样,前一个Mapper的输出结果直接重定向到后一个Mapper的输入,形成流水线。 其调用形式如下:

...        //预处理
ChainMapper.addMapper(...);
ChainReducer.setReducer(...);
ChainReducer.addMapper(...);
... //后处理
//addMapper()调用的方法形式如下:
public static void addMapper(Job job,
Class< extends Mapper> mclass,
Class< extends K1> inputKeyClass,
Class< extends V1> inputValueClass,
Class< extends K2> outputKeyClass,
Class< extends V2> outputValueClass,
Configuration conf
)

addMapper()方法有8个参数。第一个和最后一个分别为全局的Job和本地的configuration对象。第二个参数是 Mapper类,负责数据处理。余下4个参数 inputKeyClass、inputValueClass、outputKeyClass和outputValueClass是这个Mapper类中输入/输出类的类型。ChainReducer专门提供了一个setReducer()方法来设置整个作业唯一的Reducer,语法与addMapper()方法类似。

线性链式 MapReduce 的示例代码如下所示。

public void function throws IOException {
Configuration conf = new Configuration();
Job job = new Job(conf); job.setJobName("chainjob");
job.setInputFormat(TextInputFormat.class);
job.setOutputFormat(TextOutputFormat.class); FileInputFormat.addInputPath(job, in);
FileOutputFormat.setOutputPath(job, out);
//在作业中添加 Map1 阶段
Configuration map1conf = new Configuration(false);
ChainMapper.addMapper(job, Map1.class, LongWritable.class, Text.class,Text.class, Text.class, true, map1conf);
//在作业中添加 Map2 阶段
Configuration map2conf = new Configuration(false);
ChainMapper.addMapper(job, Map2.class, Text.class, Text.class,LongWritable.class, Text.class, true, map2conf);
//在作业中添加 Reduce 阶段
Configuration reduceconf = new Configuration(false);
ChainReducer.setReducer(job,Reduce.class,LongWritable.class,Text.class,Text.class,Text.class,true,reduceconf);
//在作业中添加 Map3 阶段
Configuration map3conf = new Configuration(false);
ChainReducer.addMapper(job,Map3.class,Text.class,Text.class,LongWritable.class,Text.class,true,map3conf);
//在作业中添加 Map4 阶段
Configuration map4conf = new Configuration(false);
ChainReducer.addMapper(job,Map4.class,LongWritable.class,Text.class,LongWritable.class,Text.class,true,map4conf); job.waitForCompletion(true);
}

注意:对于任意一个MapReduce作业,Map和Reduce阶段可以有无限个Mapper,但是Reduce只能有一个。所以包含多个Reduce的作业,不能使用 ChainMapper/ChainReduce来完成。

MapReduce工作流多种实现方式的更多相关文章

  1. Spark源码分析:多种部署方式之间的区别与联系(转)

    原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...

  2. C#高性能TCP服务的多种实现方式

    哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣,为了吸引眼球所以标题中一定要突出,其实我更喜欢的标题是<猴赛雷,C#编写TCP服务的花样姿势!>. 本篇文章的主 ...

  3. C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍

    在前面一系列文章中,我们可以看到微信自定义菜单的重要性,可以说微信公众号账号中,菜单是用户的第一印象,我们要规划好这些菜单的内容,布局等信息.根据微信菜单的定义,我们可以看到,一般菜单主要分为两种,一 ...

  4. 顺序表及其多种实现方式 --- C/C++

    所谓顺序表,即线性表的顺序存储结构.下面给出的是数据结构---线性表的定义. ADT List{ 数据对象: 线性表的数据对象的集合为{a1,a2,a3,...,an},每个元素的类型为ElemTyp ...

  5. Android开发中怎样调用系统Email发送邮件(多种调用方式)

    在Android中调用其他程序进行相关处理,几乎都是使用的Intent,所以,Email也不例外,所谓的调用Email,只是说Email可以接收Intent并做这些事情 我们都知道,在Android中 ...

  6. Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护

    Android数据加密概述及多种加密方式 聊天记录及账户加密 提供高质量的数据保护 数据加密又称password学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文.而解密则是通过解密 ...

  7. spring 文件模板下载多种实现方式

    针对于文件的下载,我们有很多种实现方式.业务场景是这样子的,要实现Excel文件的导入和导出功能,问题对于java的POI操作没有问题,所以实现文件的下载就相对简单,只需要从数据库取出相关的数据,针对 ...

  8. C# 高性能 TCP 服务的多种实现方式

    哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣,为了吸引眼球所以标题中一定要突出,其实我更喜欢的标题是<猴赛雷,C# 编写 TCP 服务的花样姿势!>. 本篇文 ...

  9. SVN服务的模式和多种访问方式 多种访问原理图解与优缺点

    SVN企业应用场景 SVN任是当前企业的主流.git正在发展,未来会成为主流.如果大家精力足够,建议同时掌握. 1.4运维人员掌握版本管理 对于版本管理系统,运维人员需要掌握的技术点: 1.安装.部署 ...

随机推荐

  1. Failure to find xxx in xxx was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced @ xxx

    问题: 在linux服务器上使用maven编译war时报错: 16:41:35 [FATAL] Non-resolvable parent POM for ***: Failure to find * ...

  2. 基于Caffe的Large Margin Softmax Loss的实现(中)

    小喵的唠叨话:前一篇博客,我们做完了L-Softmax的准备工作.而这一章,我们开始进行前馈的研究. 小喵博客: http://miaoerduo.com 博客原文:  http://www.miao ...

  3. Sql Server系列:SQL语句查询数据库中表、视图、存储过程等组成

    1. 查看用户表 select name from sys.tables select name from sys.objects where type='U' select name from sy ...

  4. 跨域的jsonP

    1.出现原因:因为web中的同源策略(域名,协议,端口号)限制了跨域访问.   2.区别于json (个人理解)json是数据交换格式,jsonp是数据通信中的交互方式   3.jsonp的get与p ...

  5. Vue1.0 的技术栈

    vuejs概述 Vue.js是用于构建交互式的Web界面的库.它提供了MVVM数据绑定和一个可组合的组件系统,具有简单.灵活的API. 结合node.js 可以实现前后端开发从物理上的分离.使前端负责 ...

  6. 从零开始编写自己的C#框架(15)——Web层后端登陆功能

    对于一个后端管理系统,最重要内容之一的就是登陆页了,无论是安全验证.用户在线记录.相关日志记录.单用户或多用户使用帐号控制等,都是在这个页面进行处理的. 1.在解决方案中创建一个Web项目,并将它设置 ...

  7. 【补充】Gitlab 部署 CI 持续集成

    上一篇:<劈荆斩棘:Gitlab 部署 CI 持续集成> 上一篇所配置的.gitlab-ci.yml: stages: - build - test before_script: - ec ...

  8. 无限循环轮播图之结构布局(原生JS)

    html部分 <div class="box" id="box"> <ul> <li><img src="i ...

  9. Oracle数据库文件路径变更

    环境:RHEL 6.4 + Oracle 11.2.0.3 情景一:只是部分普通数据文件迁移,可以在线操作. 1.将对应表空间offline,移动数据文件到新路径 2.数据文件alter databa ...

  10. 应用层之E-mail服务及javaMail邮件发送的知识总结

    关于Email服务你需要知道的知识点: 概述: 今天来介绍一下应用层的电子邮件服务,我们每天几乎都在用,电子邮件(email)服务也是一种基于C/S模式的服务,它采用的是一种"存储-转发&q ...