【持续更新中...】
定义
MapReduce是一个分布式运算程序的编程框架,用于Hadoop数据分析的核心框架。
MapReduce的核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。
优缺点
1.优点
1.易于编程:用户只关心业务逻辑,实现框架接口即可
2.良好扩展性:可动态增加服务器,解决计算资源不够的问题
3.高容错性:任何一个节点挂掉,可以将任务转移到其他节点
4.海量计算:TB/PB级别
2.缺点
1.不擅长实时计算:例如MySQL毫秒级查询
2.不擅长流式计算:例如Sparkstreaming、Flink
3.不擅长DAG有向无环图:迭代式计算(可以的,但Spark更擅长,基于内存)
常用数据类型
Java类型 | Hadoop Writable类型 |
---|---|
Boolean | BooleanWritable |
Byte | ByteWriteable |
Int | IntWritable |
Float | FloatWritable |
Long | LongWritable |
Double | DoubleWritable |
String | Text |
Map | MapWritable |
Array | ArrayWritable |
Null | NullWritable |
MapReduce进程
一个完整的MapReduce程序在分布式运行时有三类实例进程:
1.MrAppMaster:负责整个程序的远程帝都及状态协调
2.MapTask:负责Map阶段整个数据处理流程
3.ReduceTask:负责Reduce阶段
MapReduce编程规范
1.Mapper阶段
(1)用户自定义的Mapper要继承自己的父类
(2)Mapper的输入数据是KV对的形式(可自定义类型)
(3)Mapper中的业务逻辑写在map()中
(4)Mapper的输出数据是KV对的形式(可自定义类型)
(5)map()方法(MapTask进程)对每一个<K,V>调用一次
2.Reducer阶段
(1)用户自己定义的Reducer要继承自己的父类
(2)Reducer的输入数据类型对应Mapper的输出数据类型
(3)Reducer的业务逻辑写在reduce()方法中
(4)ReduceTask进程对每一组相同的key的<k,v>组调用一次reduce()方法
3.Driver阶段
相当于Yarn集群的客户端,用于提交程序到Yarn集群,提交的是封装了MapReduce程序相关运行参数的job对象。
1.获取配置信息,获取job对象实例
2.指定本程序的jar包所在本地路径
3.关联Mapper/Reducer业务类
4.指定Mapper输出数据的kv类型
5.指定最终输出数据的kv类型
6.指定job的输入原始文件所在目录
7.指定job输出结果所在目录
8.提交作业
WordCount示例
/**
* KEYIN:map阶段输入的key类型,偏移量:LongWritable
* VALUEIN:map阶段输入value类型:Text
* KEYOUT:map阶段输出的key类型:Text
* VALUEOUT:map阶段输出的value类型:IntWritable
*/
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {
private Text outK = new Text();
private IntWritable outV = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split(" ");
for(String word:words){
outK.set(word);
context.write(outK,outV);
}
}
}
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
private IntWritable outV = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable value : values) {
sum += value.get();
}
outV.set(sum);
context.write(key,outV);
}
}
public class WordCountDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
//1.获取job
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2.设置jar包路径
job.setJarByClass(WordCountDriver.class);
//3.关联mapper和reducer
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4.设置map输出的kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5.设置最终输出的kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.设置输入路径和输出路径
FileInputFormat.setInputPaths(job,new Path("Data/input/TestData"));
FileOutputFormat.setOutputPath(job,new Path("Data/output/TestResult"));
//7.提交作业
boolean result = job.waitForCompletion(true);
System.exit(result?0:1);
}
}