Hadoop: MapReduce2多个job串行处理
复杂的MapReduce处理中,往往需要将复杂的处理过程,分解成多个简单的Job来执行,第1个Job的输出做为第2个Job的输入,相互之间有一定依赖关系。以上一篇中的求平均数为例,可以分解成三个步骤:
1. 求Sum
2. 求Count
3. 计算平均数
每1个步骤看成一个Job,其中Job3必须等待Job1、Job2完成,并将Job1、Job2的输出结果做为输入,下面的代码演示了如何将这3个Job串起来
package yjmyzz.mr.job.link; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import yjmyzz.util.HDFSUtil; import java.io.IOException; public class Avg2 { private static final Text TEXT_SUM = new Text("SUM");
private static final Text TEXT_COUNT = new Text("COUNT");
private static final Text TEXT_AVG = new Text("AVG"); //计算Sum
public static class SumMapper
extends Mapper<LongWritable, Text, Text, LongWritable> { public long sum = 0; public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
sum += Long.parseLong(value.toString());
} protected void cleanup(Context context) throws IOException, InterruptedException {
context.write(TEXT_SUM, new LongWritable(sum));
} } public static class SumReducer extends Reducer<Text, LongWritable, Text, LongWritable> { public long sum = 0; public void reduce(Text key, Iterable<LongWritable> values, Context context)
throws IOException, InterruptedException {
for (LongWritable v : values) {
sum += v.get();
}
context.write(TEXT_SUM, new LongWritable(sum));
} } //计算Count
public static class CountMapper
extends Mapper<LongWritable, Text, Text, LongWritable> { public long count = 0; public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
count += 1;
} protected void cleanup(Context context) throws IOException, InterruptedException {
context.write(TEXT_COUNT, new LongWritable(count));
} } public static class CountReducer extends Reducer<Text, LongWritable, Text, LongWritable> { public long count = 0; public void reduce(Text key, Iterable<LongWritable> values, Context context)
throws IOException, InterruptedException {
for (LongWritable v : values) {
count += v.get();
}
context.write(TEXT_COUNT, new LongWritable(count));
} } //计算Avg
public static class AvgMapper
extends Mapper<LongWritable, Text, LongWritable, LongWritable> { public long count = 0;
public long sum = 0; public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String[] v = value.toString().split("\t");
if (v[0].equals("COUNT")) {
count = Long.parseLong(v[1]);
} else if (v[0].equals("SUM")) {
sum = Long.parseLong(v[1]);
}
} protected void cleanup(Context context) throws IOException, InterruptedException {
context.write(new LongWritable(sum), new LongWritable(count));
} } public static class AvgReducer extends Reducer<LongWritable, LongWritable, Text, DoubleWritable> { public long sum = 0;
public long count = 0; public void reduce(LongWritable key, Iterable<LongWritable> values, Context context)
throws IOException, InterruptedException {
sum += key.get();
for (LongWritable v : values) {
count += v.get();
}
} protected void cleanup(Context context) throws IOException, InterruptedException {
context.write(TEXT_AVG, new DoubleWritable(new Double(sum) / count));
} } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); String inputPath = "/input/duplicate.txt";
String maxOutputPath = "/output/max/";
String countOutputPath = "/output/count/";
String avgOutputPath = "/output/avg/"; //删除输出目录(可选,省得多次运行时,总是报OUTPUT目录已存在)
HDFSUtil.deleteFile(conf, maxOutputPath);
HDFSUtil.deleteFile(conf, countOutputPath);
HDFSUtil.deleteFile(conf, avgOutputPath); Job job1 = Job.getInstance(conf, "Sum");
job1.setJarByClass(Avg2.class);
job1.setMapperClass(SumMapper.class);
job1.setCombinerClass(SumReducer.class);
job1.setReducerClass(SumReducer.class);
job1.setOutputKeyClass(Text.class);
job1.setOutputValueClass(LongWritable.class);
FileInputFormat.addInputPath(job1, new Path(inputPath));
FileOutputFormat.setOutputPath(job1, new Path(maxOutputPath)); Job job2 = Job.getInstance(conf, "Count");
job2.setJarByClass(Avg2.class);
job2.setMapperClass(CountMapper.class);
job2.setCombinerClass(CountReducer.class);
job2.setReducerClass(CountReducer.class);
job2.setOutputKeyClass(Text.class);
job2.setOutputValueClass(LongWritable.class);
FileInputFormat.addInputPath(job2, new Path(inputPath));
FileOutputFormat.setOutputPath(job2, new Path(countOutputPath)); Job job3 = Job.getInstance(conf, "Average");
job3.setJarByClass(Avg2.class);
job3.setMapperClass(AvgMapper.class);
job3.setReducerClass(AvgReducer.class);
job3.setMapOutputKeyClass(LongWritable.class);
job3.setMapOutputValueClass(LongWritable.class);
job3.setOutputKeyClass(Text.class);
job3.setOutputValueClass(DoubleWritable.class); //将job1及job2的输出为做job3的输入
FileInputFormat.addInputPath(job3, new Path(maxOutputPath));
FileInputFormat.addInputPath(job3, new Path(countOutputPath));
FileOutputFormat.setOutputPath(job3, new Path(avgOutputPath)); //提交job1及job2,并等待完成
if (job1.waitForCompletion(true) && job2.waitForCompletion(true)) {
System.exit(job3.waitForCompletion(true) ? 0 : 1);
} } }
输入文本在上一篇可以找到,上面这段代码的主要思路:
1. Sum和Count均采用相同的输入/input/duplicate.txt,然后将各自的处理结果分别输出到/output/max/及/output/count/下
2. Avg从/output/max及/output/count获取结果做为输入,然后根据Key值不同,拿到sum和count的值,最终计算并输出到/output/avg/下
Hadoop: MapReduce2多个job串行处理的更多相关文章
- Hadoop基础-Protocol Buffers串行化与反串行化
Hadoop基础-Protocol Buffers串行化与反串行化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们之前学习过很多种序列化文件格式,比如python中的pickl ...
- Hadoop基础-Apache Avro串行化的与反串行化
Hadoop基础-Apache Avro串行化的与反串行化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Apache Avro简介 1>.Apache Avro的来源 ...
- 实例理解mapreduce任务的串行运行过程
一.准备: eclipse,hadoop集群 注意:为了方便测试和修改,我用的是 windows 连接hadoop集群,这样在windows 下直接就能够执行 mapreduce 任务,方便程序调试. ...
- JQuery使用deferreds串行多个ajax请求
使用JQuery对多个ajax请求串行执行. HTML代码: <a href="#">Click me!</a> <div></div&g ...
- iOS:GCD理解1(同步-异步、串行-并行)
1.并行-异步(ST1与ST2抢占资源) 1-1).获取 并行(全局)队列 ,DISPATCH_QUEUE_PRIORITY_DEFAULT 为默认优先级. dispatch_queue_t queu ...
- 【Java EE 学习 72 下】【数据采集系统第四天】【移动/复制页分析】【使用串行化技术实现深度复制】
一.移动.复制页的逻辑实现 移动.复制页的功能是在设计调查页面的时候需要实现的功能.规则是如果在同一个调查中的话就是移动,如果是在不同调查中的就是复制. 无论是移动还是复制,都需要注意一个问题,那就是 ...
- 大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)
返回目录 并行是.net4.5主打的技术,同时被封装到了System.Threading.Tasks命名空间下,对外提供了静态类Parallel,我们可以直接使用它的静态方法,它可以并行一个委托数组, ...
- JVM_垃圾回收串行、并行、并发算法(总结)
一.串行 JDK1.5前的默认算法 缺点是只有一个线程,执行垃圾回收时程序停止的时间比较长 语法 -XX:+UseSerialGC 新生代.老年代使用串行回收 新生代复制算法 老年代标记-压缩 示例图 ...
- ios--进程/多线程/同步任务/异步任务/串行队列/并行队列(对比分析)
现在先说两个基本的概念,啥是进程,啥是线程,啥又是多线程;先把这两个总是给弄清再讲下面的 进程:正在进行的程序,我们就叫它进程. 线程:线程就是进程中的一个独立的执行路径.这句话怎么理解呢! 一个程序 ...
随机推荐
- linux 中的 tar 解压
Type at the command prompt tar xvzf file-1.0.tar.gz - tgfo uncompress a gzip tar file (.tgz or .tar. ...
- 自动化部署教程(一) redhat安装jenkins
自动化部署教程(一) redhat安装jenkins 源配置: sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.or ...
- Oracle 外连接和 (+)号的用法
对于外连接,Oracle中可以使用“(+)”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN,下面将配合实例一一介绍.1. LEFT OUTER JOIN:左外关联 SELEC ...
- Javascript之旅——第八站:说说instanceof踩了一个坑
前些天写js遇到了一个instanceof的坑,我们的页面中有一个iframe,我在index页面中计算得到了一个array,然后需要传递到Flight页面 这个嵌套的iframe中的一个函数(Sea ...
- 关于GUID的相关知识
全局唯一标识符(GUID,Globally Unique Identifier)是一种由算法生成的二进制长度为128位的数字标识符.GUID主要用于在拥有多个节点.多台计算机的网络或系统中.在理想情 ...
- js中的三个编码函数:escape,encodeURI,encodeURIComponent
1. eacape(): 该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / .其他所有的字符都会被转义序列替换.其它情况下es ...
- 2------------NLPIR(ICTCLAS2016)分词系统添加用户词典功能
备注:win7 64位系统,netbeans编程 基本代码框架参见我的另一篇文章:NLPIR分词功能 代码实现: package cwordseg; import java.io.Unsupporte ...
- ARC的原理详解
1,ARC的本质 ARC本质是NSAutoreleasePool的直接应用, @autorelease{ return UIApplicationMain(argc, argv, nil, NSStr ...
- 免费股票数据API接口
免费股票数据API接口提供沪深.香港.美国股市信息. 1.沪深股市 2.香港股市 3.美国股市 4.香港股市列表 5.美国股市列表 6.深圳股市列表 7.沪股列表 API文档:https://www. ...
- [转]Asp.net MVC使用Filter解除Session, Cookie等依赖
本文转自:http://www.cnblogs.com/JustRun1983/p/3279139.html 本文,介绍了Filter在MVC请求的生命周期中的作用和角色,以及Filter的一些常用应 ...