Hadoop(十七)之MapReduce作业配置与Mapper和Reducer类
前言
前面一篇博文写的是Combiner优化MapReduce执行,也就是使用Combiner在map端执行减少reduce端的计算量。
一、作业的默认配置
MapReduce程序的默认配置
1)概述
在我们的MapReduce程序中有一些默认的配置。所以说当我们程序如果要使用这些默认配置时,可以不用写。
我们的一个MapReduce程序一定会有Mapper和Reducer,但是我们程序中不写的话,它也有默认的Mapper和Reducer。
当我们使用默认的Mapper和Reducer的时候,map和reducer的输入和输出都是偏移量和数据文件的一行数据,所以就是相当于原样输出!
2)默认的MapReduce程序
/**
* 没有指定Mapper和Reducer的最小作业配置
*/
public class MinimalMapReduce {
public static void main(String[] args) throws Exception{
// 构建新的作业
Configuration conf=new Configuration();
Job job = Job.getInstance(conf, "MinimalMapReduce");
job.setJarByClass(MinimalMapReduce.class);
// 设置输入输出路径
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// ᨀ交作业运行
System.exit(job.waitForCompletion(true)?0:1);
}
}
输入是:
输出是:
二、作业的配置方式
MapReduce的类型配置
1)用于配置类型的属性
在命令行中,怎么去配置呢?
比如说mapreduce.job.inputformat.class。首先我们要继承Configured实现Tool工具才能这样去指定:
-Dmapreduce.job.inputformat.class = 某一个类的类全名(一定要记得加报名)
这是Map端的输出类型控制
这是整个MapReduce程序输出类型控制,其实就是reduce的类型格式控制
2)No Reducer的MapReduce程序--Mapper
第一步:写一个TokenCounterMapper继承Mapper
/**
* 将输入的文本内容拆分为word,做一个简单输出的Mapper
*/
public class TokenCounterMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
private Text word=new Text();
private static final IntWritable one=new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
StringTokenizer itr=new StringTokenizer(value.toString());
while(itr.hasMoreTokens()){
word.set(itr.nextToken());
context.write(word, one);
}
}
}
第二步:写一个NoReducerMRDriver完成作业配置
/**
*没有设置Reducer的MR程序
*/
public class NoReducerMRDriver {
public static void main(String[] args) throws Exception {
// 构建新的作业
Configuration conf=new Configuration();
Job job = Job.getInstance(conf, "NoReducer");
job.setJarByClass(NoReducerMRDriver.class);
// 设置Mapper
job.setMapperClass(TokenCounterMapper.class);
// 设置reducer的数量为0
job.setNumReduceTasks(0);
// 设置输出格式
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 设置输入输出路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// ᨀ交运行作业
System.exit(job.waitForCompletion(true)?0:1);
}
}
输入:
结果:
注意:如果作业拥有0个Reducer,则Mapper结果直接写入OutputFormat而不经key值排序。
3)No Mapper的MapReduce程序--Reducer
第一步:写一个TokenCounterReducer继承Reducer
/**
* 将reduce输入的values内容拆分为word,做一个简单输出的Reducer
*/
public class TokenCounterReducer extends Reducer<LongWritable, Text, Text, IntWritable>{
private Text word=new Text();
private static final IntWritable one=new IntWritable(1);
@Override
protected void reduce(LongWritable key, Iterable<Text> values,Reducer<LongWritable, Text, Text, IntWritable>.Context context)
throws IOException, InterruptedException {
// TODO Auto-generated method stub
for(Text value:values){
StringTokenizer itr=new StringTokenizer(value.toString());
while(itr.hasMoreTokens()){
word.set(itr.nextToken());
context.write(word, one);
}
}
}
}
第二步:写一个NoMapperMRDrive完成作业配置
/**
*没有设置Mapper的MR程序
*/
public class NoMapperMRDriver {
public static void main(String[] args) throws Exception {
// 构建新的作业
Configuration conf=new Configuration();
Job job = Job.getInstance(conf, "NoMapper");
job.setJarByClass(NoMapperMRDriver.class);
// 设置Reducer
job.setReducerClass(TokenCounterReducer.class);
// 设置输出格式
job.setMapOutputKeyClass(LongWritable.class);
job.setMapOutputValueClass(Text.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 设置输入输出路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// ᨀ交运行作业
System.exit(job.waitForCompletion(true)?0:1);
}
}
输入:
输出:
三、Mapper类和Reducer类以及它们的子类(实现类)
3.1、Mapper概述
Mapper:封装了应用程序Mapper阶段的数据处理逻辑
1)ChainMapper
方便用户编写链式Map任务, 即Map阶段包含多个Mapper,即可以别写多个自定义map去参与运算。 2)InverseMapper
一个能交换key和value的Mapper 3)RegexMapper
检查输入是否匹配某正则表达式, 输出匹配字符串和计数器(用的很少) 4)TockenCounterMapper
将输入分解为独立的单词, 输出个单词和计数器(以空格分割单词,value值为1)
3.2、Reducer概述
Mapper:封装了应用程序Mapper阶段的数据处理逻辑
1)ChainMapper:
方便用户编写链式Map任务, 即Map阶段只能有一个Reducer,后面还可以用ChainMapper去多加Mapper。
2)IntSumReducer/LongSumReducer
对各key的所有整型值求和
3.2、写一个实例去使用
注意:这里用到了一个输入格式为KeyValueTextInputFormat,我们查看源码注释:
我们需要用mapreduce.input.keyvaluelinerecordreader.key.value.separator去指定key和value的分隔符是什么,它的默认分隔符是"t"也就是tab键。
这个需要在配置文件中去指定,但是我们知道在配置文件中能设置的在程序中也是可以设置的。
conf.set("mapreduce.input.keyvaluelinerecordreader.key.value.separator",",");
代码实现:
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.chain.ChainMapper;
import org.apache.hadoop.mapreduce.lib.chain.ChainReducer;
import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.lib.map.InverseMapper;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.mapreduce.lib.reduce.IntSumReducer;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class PatentReference_0010 extends Configured implements Tool{
static class PatentReferenceMapper extends Mapper<Text,Text,Text,IntWritable>{
private IntWritable one=new IntWritable(1);
@Override
protected void map(Text key,Text value,Context context) throws IOException, InterruptedException{
context.write(key,one);
}
}
@Override
public int run(String[] args) throws Exception{
Configuration conf=getConf();
Path input=new Path(conf.get("input"));
Path output=new Path(conf.get("output"));
conf.set("mapreduce.input.keyvaluelinerecordreader.key.value.separator",",");
Job job=Job.getInstance(conf,this.getClass().getSimpleName());
job.setJarByClass(this.getClass());
ChainMapper.addMapper(job,InverseMapper.class,
// 输入的键值类型由InputFormat决定
Text.class,Text.class,
// 输出的键值类型与输入的键值类型相反
Text.class,Text.class,conf);
ChainMapper.addMapper(job,PatentReferenceMapper.class,
// 输入的键值类型由前一个Mapper输出的键值类型决定
Text.class,Text.class,
Text.class,IntWritable.class,conf);
ChainReducer.setReducer(job,IntSumReducer.class,
Text.class,IntWritable.class,
Text.class,IntWritable.class,conf);
ChainReducer.addMapper(job,InverseMapper.class,
Text.class,IntWritable.class,
IntWritable.class,Text.class,conf);
job.setInputFormatClass(KeyValueTextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
KeyValueTextInputFormat.addInputPath(job,input);
TextOutputFormat.setOutputPath(job,output);
return job.waitForCompletion(true)?0:1;
}
public static void main(String[] args) throws Exception{
System.exit(ToolRunner.run(new P00010_PatentReference_0010(),args));
}
}
在Job job=Job.getInstance(conf,this.getClass().getSimpleName());设置中,job把conf也就是配置文件做了一个拷贝,因为hadoop要重复利用一个对象,如果是引用的话,发现值得改变就都改变了。
喜欢就点个“推荐”哦!
- addSubView需要注意的几个点为什么要在addsubview:一个view对象后,release它?
- nodejs 命令行、自定义
- GeForce驱动EULA更新惹争议,NVIDIA的理由是这样的
- 关于HTML面试题汇总之visibility
- 加密狗进场暴富开始?请别侮辱区块链和游戏
- 程序猿的日常——Java基础之clone、序列化、字符串、数组
- [你必须知道的.NET] 第四回:后来居上:class和struct
- oc 中随机数的用法(arc4random() 、random()、CCRANDOM_0_1()
- 央行出台条码支付新规;美团打车将在7大城市上线;国产人工智能平台型芯片首发;苹果就降速门致歉
- 阿三又让全球看笑话,无人驾驶的地铁名不副实,还直接跑到大街上
- 盘点:2017年度这些科学大事件,哪个给您印象最深?
- 跳台阶问题
- mac下使用github
- CSS3新特性应用之结构与布局
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- kubernetes(十七) Helm V3 入门到放弃
- Dockerfile文件万字全面解析
- Go测试开发(一) 怎么写Go代码
- kubernetes(十八)集群网路
- Nginx性能监控与调优
- pytest封神之路第二步 132个命令行参数用法
- Jumpserver2.2部署文档
- Golang多线程简单斗地主
- Tomcat性能监控与调优
- Vue+SpringBoot项目实战(一) 搭建环境
- kubernetes(十九) Ceph存储入门
- Java并发编程(8)- 应用限流及其常见算法
- 字符集其实很简单
- kubernetes(二十)SpringCloud微服务容器化迁移
- HashMap? ConcurrentHashMap? 相信看完这篇没人能难住你!