一、mapreduce多job串联

1、需求

一个稍复杂点的处理逻辑往往需要多个 mapreduce 程序串联处理,多 job 的串联可以借助 mapreduce 框架的 JobControl 实现

2、实例

以下有两个 MapReduce 任务,分别是 Flow 的 SumMR 和 SortMR,其中有依赖关系: SumMR 的输出是 SortMR 的输入,所以 SortMR 的启动得在 SumMR 完成之后

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job jobsum = Job.getInstance(conf);
jobsum.setJarByClass(RunManyJobMR.class);
jobsum.setMapperClass(FlowSumMapper.class);
jobsum.setReducerClass(FlowSumReducer.class);
jobsum.setMapOutputKeyClass(Text.class);
jobsum.setMapOutputValueClass(Flow.class);
jobsum.setCombinerClass(FlowSumReducer.class);
jobsum.setOutputKeyClass(Text.class);
jobsum.setOutputValueClass(Text.class);
FileInputFormat.setInputPaths(jobsum, "d:/flow/input");
FileOutputFormat.setOutputPath(jobsum, new Path("d:/flow/output12"));
Job jobsort = Job.getInstance(conf);
jobsort.setJarByClass(RunManyJobMR.class);
jobsort.setMapperClass(FlowSortMapper.class);
jobsort.setReducerClass(FlowSortReducer.class);
jobsort.setMapOutputKeyClass(Flow.class);
jobsort.setMapOutputValueClass(Text.class);
jobsort.setOutputKeyClass(NullWritable.class);
jobsort.setOutputValueClass(Flow.class);
FileInputFormat.setInputPaths(jobsort, "d:/flow/output12");
FileOutputFormat.setOutputPath(jobsort, new Path("d:/flow/sortoutput12"));
ControlledJob sumcj = new ControlledJob(jobsum.getConfiguration());
ControlledJob sortcj = new ControlledJob(jobsort.getConfiguration());
sumcj.setJob(jobsum);
sortcj.setJob(jobsort);
// 设置作业依赖关系
sortcj.addDependingJob(sumcj);
JobControl jc = new JobControl("flow sum and sort");
jc.addJob(sumcj);
jc.addJob(sortcj);
Thread jobThread = new Thread(jc);
jobThread.start();
while(!jc.allFinished()){
Thread.sleep(500);
}
jc.stop();
}

二、topn算法实现——自定义GroupComparator

1、需求

在统计学生成绩的小项目中,现在有一个需求:
   求出每个班参考学生成绩最高的学生的信息,班级,姓名和平均分

2、分析

(1)利用“班级和平均分”作为 key,可以将 map 阶段读取到的所有学生成绩数据按照班级 和成绩排倒序,发送到 reduce
(2)在 reduce 端利用 GroupingComparator 将班级相同的 kv 聚合成组,然后取第一个即是最 大值
   3、实现

数据类似于

computer	huangxiaoming	85	86	41	75	93	42	85
computer xuzheng 54 52 86 91 42
computer huangbo 85 42 96 38
english zhaobenshan 54 52 86 91 42 85 75
english liuyifei 85 41 75 21 85 96 14
algorithm liuyifei 75 85 62 48 54 96 15
computer huangjiaju 85 75 86 85 85
english liuyifei 76 95 86 74 68 74 48

  第一步:先把分组和排序字段都综合到一个自定义对象里

package com.ghgj.mr.topn;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;
public class ClazzScore implements WritableComparable<ClazzScore>{
private String clazz;
private Double score;
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public ClazzScore(String clazz, Double score) {
super();
this.clazz = clazz;
this.score = score;
}
public ClazzScore() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return clazz + "\t" + score;
}
@Override
public void write(DataOutput out) throws IOException {
out.writeUTF(clazz);
out.writeDouble(score);
}
@Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
this.clazz = in.readUTF();
this.score = in.readDouble();
}
/**
* key 排序
*/
@Override
public int compareTo(ClazzScore cs) {
int it = cs.getClazz().compareTo(this.clazz);
if(it == 0){
return (int) (cs.getScore() - this.score);
}else{
return it;
}
}
}

  第二步:编写排序之后的 ClazzScore 数据传入 ReduceTask 的分组规则

package com.ghgj.mr.topn;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
public class ClazzScoreGroupComparator extends WritableComparator{
ClazzScoreGroupComparator(){
super(ClazzScore.class, true);
}
/**
* 决定输入到 reduce 的数据的分组规则
*/
@Override
public int compare(WritableComparable a, WritableComparable b) {
// TODO Auto-generated method stub
ClazzScore cs1 = (ClazzScore)a;
ClazzScore cs2 = (ClazzScore)b;
int it = cs1.getClazz().compareTo(cs2.getClazz());
return it;
}
}

  第三步:编写mapreduce程序

package com.ghgj.mr.topn;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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;
/**
* TopN 问题
*/
public class ScoreTop1MR {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
job.setJarByClass(ScoreTop1MR.class);
job.setMapperClass(ScoreTop1MRMapper.class);
job.setReducerClass(ScoreTop1MRReducer.class);
job.setOutputKeyClass(ClazzScore.class);
job.setOutputValueClass(DoubleWritable.class);
// 设置传入 reducer 的数据分组规则
job.setGroupingComparatorClass(ClazzScoreGroupComparator.class);
FileInputFormat.setInputPaths(job, "d:/score_all/input");
Path p = new Path("d:/score_all/output1");
FileSystem fs = FileSystem.newInstance(conf);
if(fs.exists(p)){
fs.delete(p, true);
}
FileOutputFormat.setOutputPath(job, p);
boolean status = job.waitForCompletion(true);
System.exit(status ? 0 : 1);
}
static class ScoreTop1MRMapper extends Mapper<LongWritable, Text, ClazzScore,
DoubleWritable>{
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException,
InterruptedException {
String[] splits = value.toString().split("\t");
ClazzScore cs = new ClazzScore(splits[0], Double.parseDouble(splits[2]));
context.write(cs, new DoubleWritable(Double.parseDouble(splits[2])));
}
}
static class ScoreTop1MRReducer extends Reducer<ClazzScore, DoubleWritable, ClazzScore,
DoubleWritable>{
@Override
protected void reduce(ClazzScore cs, Iterable<DoubleWritable> scores, Context
context) throws IOException, InterruptedException {
// 按照规则,取每组的第一个就是 Top1
context.write(cs, scores.iterator().next());
}
}
}

三、Mapreduce全局计数器

1、需求

在实际生产代码中,常常需要将数据处理过程中遇到的不合规数据行进行全局计数,类似这 种需求可以借助 MapReduce 框架中提供的全局计数器来实现
     2、实例

以下是一个利用全局计数器来统计一个目录下所有文件出现的单词总数和总行数

package com.ghgj.mr.counter;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
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; public class WordCount { enum MyWordCounter{COUNT_LINES,COUNT_WORD}
// enum Weekday{MONDAY, TUESDAY, WENSDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} public static void main(String[] args) throws Exception {
// 指定hdfs相关的参数
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
// 设置jar包所在路径
job.setJarByClass(WordCount.class);
job.setMapperClass(WCMapper.class);
job.setReducerClass(WCReducer.class); // 指定reducetask的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class); // 本地路径
Path inputPath = new Path("d:/wordcount/input");
Path outputPath = new Path("d:/wordcount/output"); FileSystem fs = FileSystem.get(conf);
if(fs.exists(outputPath)){
fs.delete(outputPath, true);
}
FileInputFormat.setInputPaths(job, inputPath);
FileOutputFormat.setOutputPath(job, outputPath); // 最后提交任务
boolean waitForCompletion = job.waitForCompletion(true);
System.exit(waitForCompletion?0:1);
} private static class WCMapper extends Mapper<LongWritable, Text, Text, LongWritable>{
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException { // COUNT_LINES++;
context.getCounter(MyWordCounter.COUNT_LINES).increment(1L); // 在此写maptask的业务代码
String[] words = value.toString().split(" ");
for(String word: words){
context.write(new Text(word), new LongWritable(1));
context.getCounter(MyWordCounter.COUNT_WORD).increment(1L);
}
}
} private static class WCReducer extends Reducer<Text, LongWritable, Text, LongWritable>{
@Override
protected void reduce(Text key, Iterable<LongWritable> values, Context context)
throws IOException, InterruptedException {
// 在此写reducetask的业务代码
long sum = 0;
for(LongWritable v: values){
sum += v.get();
}
context.write(key, new LongWritable(sum));
}
}
}

  或者:另一种情况

package com.ghgj.mr.counter;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class CounterWordCount {
enum CouterWordCountC{COUNT_WORDS, COUNT_LINES}
public static void main(String[] args) throws Exception {
// 指定 hdfs 相关的参数
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
// 设置 jar 包所在路径
job.setJarByClass(CounterWordCount.class);
job.setMapperClass(WCCounterMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
// 本地路径
Path inputPath = new Path("d:/wordcount/input");
FileInputFormat.setInputPaths(job, inputPath);
job.setNumReduceTasks(0);
Path outputPath = new Path("d:/wordcount/output");
FileSystem fs = FileSystem.get(conf);
if(fs.exists(outputPath)){
fs.delete(outputPath, true);
}
FileOutputFormat.setOutputPath(job, outputPath);
// 最后提交任务
boolean waitForCompletion = job.waitForCompletion(true);
System.exit(waitForCompletion?0:1);
}
private static class WCCounterMapper extends Mapper<LongWritable, Text, Text,
LongWritable>{
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
// 统计行数,因为默认读取文本是逐行读取,所以 map 执行一次,行数+1
context.getCounter(CouterWordCountC.COUNT_LINES).increment(1L);
String[] words = value.toString().split(" ");
for(String word: words){
// 统计单词总数,遇见一个单词就+1
context.getCounter(CouterWordCountC.COUNT_WORDS).increment(1L);
}
}
}
}

  

MapReduce(三) 典型场景(一)的更多相关文章

  1. Streamr助你掌控自己的数据(2)——三种整合数据至Streamr的典型场景

    博客说明 所有刊发内容均可转载但是需要注明出处. 三种整合数据至Streamr的典型场景 本系列文档主要介绍怎么通过Streamr管理自己的DATA,整个系列包括三篇教程文档,分别是:教你5分钟上传数 ...

  2. 五大典型场景中的API自动化测试实践

    一.API 测试的基本步骤 通常来讲,API 测试的基本步骤主要包括以下三大步骤: 1.准备测试数据: 2.通过通用的或自己开发的API测试工具发起对被测API的request: 3.验证返回结果的r ...

  3. iOS容易造成循环引用的三种场景

    iOS容易造成循环引用的三种场景  ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...

  4. MapReduce(三)

    MapReduce(三) MapReduce(三): 1.关于倒叙排序前10名 1)TreeMap根据key排序 2)TreeSet排序,传入一个对象,排序按照类中的compareTo方法排序 2.写 ...

  5. SFUD+FAL+EasyFlash典型场景需求分析,并记一次实操记录

    SFUD+FAL+EasyFlash典型场景需求分析:用整个flash存储数据,上千条数据,读取得时候用easyflash很慢,估计要检索整个flash太慢了. 改进方法:分区检索. 1存数据时,根据 ...

  6. SparkSQL中产生笛卡尔积的几种典型场景以及处理策略

    [前言:如果你经常使用Spark SQL进行数据的处理分析,那么对笛卡尔积的危害性一定不陌生,比如大量占用集群资源导致其他任务无法正常执行,甚至导致节点宕机.那么都有哪些情况会产生笛卡尔积,以及如何事 ...

  7. OC与Swift混编,三种场景的实现方式

    多语言并存时期,混编成为一种必须的方式 ,在多场影中实现OC和Swift语言的并存原来是如此简单 第一种场景,App中实现混编 创建桥接文件*.h 新建一个桥接文件,New File 选择 Heade ...

  8. MapReduce(四) 典型编程场景(二)

    一.MapJoin-DistributedCache 应用 1.mapreduce join 介绍 在各种实际业务场景中,按照某个关键字对两份数据进行连接是非常常见的.如果两份数据 都比较小,那么可以 ...

  9. 从0开始学Java——JSP和Servlet——jsp转servlet出错的三个典型场景

    由于jsp终究是要转换为servlet的java文件,然后再编译为.class文件,最后才执行,那么在这过程的任何一个步骤都可能有问题,主要包括三个方面,下面逐一分析: 一.JSP转换为Servlet ...

随机推荐

  1. 前端--javaScript之简单介绍

    一.javaScript(以下简称js)的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端 ...

  2. php实现快速排序和冒泡排序

    快速排序 实现思路:把第一个元素作为标记,依次判断后续的值,如果小于它则放在左边,如果大于它则放右边,同理把左右两部分看成一个整体一直递归,最后再数组拼接起来 它的最优时间复杂度为O(nlogn)[以 ...

  3. 3星|麦肯锡合伙人《从1到N》:PPT讲稿,图表不错,讲解不够深入

    从1到N:企业数字化生存指南 两位作者是麦肯锡合伙人.全书插图比较多,图做的还比较有水平.但是相关文字不够深入,我读后的感觉是:图表不是两位执笔者做的,他们对细节不清楚,对图表涉及到的行业也缺乏深入的 ...

  4. Python基础入门(迭代器和生成器)

    1 Python迭代器 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退. 迭代器有两个基本的方法:iter() 和 ...

  5. 记录一下自己申请并使用VPS的全过程

    在学习REST API的时候,想要阅读一下谷歌爸爸的api design guide,无奈无情被墙,正好在学习云相关的技术,就想到申请一个VPS来用用. 这次我选择的是hostmybytes,原因有两 ...

  6. 从零开始的Python学习Episode 9——集合

    集合 集合是一个无序的,不重复的数据组合,是python基本的数据类型,把不同的元素组成一起就形成集合. 一.创建集合 s = set('smile')list = ['1','2','3']prin ...

  7. 第八次ScrumMeeting博客

    第八次ScrumMeeting博客 本次会议于11月2日(四)22时整在3公寓725房间召开,持续20分钟. 与会人员:刘畅.辛德泰.窦鑫泽.张安澜.赵奕.方科栋. 1. 每个人的工作(有Issue的 ...

  8. C#中的Split用法以及详解

    一.String.Split方法提供了如下6个重载函数: 名称 说明 String.Split (Char[]) 返回包含此实例中的子字符串(由指定 Char 数组的元素分隔)的 String 数组. ...

  9. php json 转换

    在PHP语言中使用JSON   作者: 阮一峰 日期: 2011年1月14日 目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它. 我写过一篇<数据类型和JSON格式& ...

  10. php异步学习(1)

    1.为啥PHP需要异步操作? 一般来说PHP适用的场合是web页面展示等耗时比较短的任务,如果对于比较花时间的操作如resize图片.大数据导入.批量发送EDM.SMS等,就很容易出现操作超时情况.你 ...