Hadoop生态圈之MapReduce
1. MapReduce概述
- 定义:
- MapReduce是一个分布式运算程序的编程框架,是用户开发基于Hadoop的数据分析应用的核心框架
- MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上
- 优点:
- MapReduce易于编程
- 它简单的实现了一些接口,就可以完成一个分布式程序,这个分布式程序可以发布到大量廉价的PC机器上运行。也就是说你你写一个分布式程序,跟写一个简单的串行程序是一模一样的,就是因为这个特点使得MapReduce编程变得非常流行。
- 良好的扩展性
- 当你的计算资源不够时,可以简单的通过增加机器来扩展它的计算能力
- 高容错性
- MapReduce设计的初衷就是使程序能够部署在廉价的PC机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,他可以把上面的计算任务转移到另一个节点上运行,不至于这个任务运行失败,而且这个过程不需要人工参与,完全是由Hadoop内部完成的
- 适合PB及以上海量数据的离线处理
- 可以实现上千台服务器集群并发工作,提高数据处理能力
- MapReduce易于编程
- 缺点:
- 不擅长实时计算
- MapReduce无法像MySQL一样,在毫秒或秒级内返回结果。
- 不擅长流式计算
- 流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态改变。这是因为MapReduce自身的设计特点决定了数据源必须是静态的
- 不擅长DAG(有向无环图)计算
- 多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常低下
- 不擅长实时计算
2.MapReduce核心思想
- 分布式的运算程序往往需要分成至少2个阶段
- 第一个阶段的MapTask并发实例,完全并行运行,互不相干。
- 第二个阶段的ReduceTask并发实例互不相关,但是他们的数据依赖于上一个阶段的所有MapTask并发实例的输出。
- MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段,如果用户的业务逻辑复杂,那就只能多个MapReduce程序,串行运行
3. 一个MapReduce进程包含三个类实例进程:
- MrAppMaster:负责整个程序的过程调度及状态协调
- MapTask:负责Map阶段的整个数据处理流程
- ReduceTask:负责Reduce阶段的整个数据处理流程
4.常用数据序列化类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQX2gV6N-1646823818323)(Hadoop生态圈之MapReduce.assets/1646810571118.png)]
5.MapReduce编程规范
用户编写的程序分为三个部分:Mapper、Reduce和Driver
-
Mapper阶段
-
用户自定义的Mapper要继承自己父类
-
Mapper的输入数据是KV对的形式(KV的类型可自定义)
-
Mapper中的业务逻辑写在map()方法中
-
Mapper中的输出数据是KV对的形式(KV的类型可自定义)
-
map()方法(MapTask进程)对每一个<K,V>调用一次
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> { Text k = new Text(); IntWritable v = new IntWritable(1); @Override protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException { //获取第一行数据并将他转换为String类型 String line = value.toString(); //对第一行进行分割 String[] words = line.split(" "); //输出 for (String word :words){ k.set(word); context.write(k,v); } } }
-
-
Reduce阶段
-
用户自定义的Reduce要继承自己的父类
-
Reduce的输入数据类型对应Mapper的输出类型数据,也是KV
-
Reduce的业务逻辑写在reduce()方法中
-
ReduceTask进程对每一个组相同k的<K,V>组调用一次reduce()方法
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { int sum; IntWritable v = new IntWritable(); @Override protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException { //累加求和 sum = 0; for (IntWritable count : values) { sum += count.get(); } //输出 v.set(sum); context.write(key, v); } }
-
-
Driver阶段
相当于YARN集群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了MapReduce程序相关运行参数的job对象public class WordCountDriver { public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException { // 获取配置信息以及获取job对象 Configuration conf = new Configuration(); Job job = Job.getInstance(conf); //关联本地Driver程序的jar job.setJarByClass(WordCountDriver.class); //关联Mapper和Reduce的jar job.setMapperClass(WordCountMapper.class); job.setReducerClass(WordCountReducer.class); //设置Mapper输出的kv类型 job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(IntWritable.class); //设置最终输出的kv类型 job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); //设置输出和输入路径 FileInputFormat.setInputPaths(job, new Path("D:\\input\\input.txt")); FileOutputFormat.setOutputPath(job,new Path("D:\\output\\output1")); //提交job boolean result = job.waitForCompletion(true); System.exit(result ? 0 : 1); } }