7,MapReduce基础
MapReduce基础
一、关于MapReduce
1.1 为什么要MapReduce
- 单机资源有限:由于单台计算机的资源有限,计算能力不足以处理海量数据;所以需要多台计算机组成分布式集群来处理海量数据。
- 分布式计算较复杂:在分布式计算中,计算任务的分发,各个主机之间的协作;程序的启动以及运行过程中的监控、容错、重试等都会变得很复杂。所以引入了MapReduce框架,框架解决了分布式开发中的复杂性,开发人员只需要将大部分工作集中在业务逻辑的开发上,从而极大的提高了工作效率。
1.2 MapReduce的定义
- MapReduce是一个分布式运算程序的编程框架,用于大规模数据集(大于1TB)的并行计算;Map(映射)和reduce(归约)是它的主要思想;它极大地方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。
二、MapReduce的优缺点
2.1 优点:
- 易于编程:只需要实现一些接口,就可以完成一个分布式程序的编写;跟编写一个串行程序一样;
- 良好的扩展性:当计算资源不足时,只需要简单的增加机器来扩展它的计算能力;
- 高容错性:当一个机器挂了之后,会自动把上面的计算任务转移到另一个节点上运行,无需人工干预;
- 海量:适合PB级海量数据的离线处理。
2.2 缺点:
- 不适合实时计算:MapReduce由于过程较为复杂,IO次数较多,所以无法做到毫秒或秒级响应;
- 不适合流式计算:流式计算的输入是动态的,可以不断添加,而MapReduce的输入是静态的;
- 不适合DAG(有向图)计算:对于多个程序之间有依赖关系,即后一个程序的输入是前一个程序的输出;虽然MapReduce也可以完成,但都是通过磁盘来传递中间数据,造成大量的磁盘IO,性能极低。
三、MapReduce的执行阶段
3.1 执行的两个阶段
Map阶段:若干个maptask并发实例,完全并行运行,互不相干。
Reduce阶段:若干个reducetask并发实例,完全并行运行,但是他们的数据依赖于Map阶段的输出。
注意:MapReduce模型只能包含一个map阶段和一个reduce阶段;如果业务逻辑非常复杂,就只能使用多个MapReduce程序,串行运行。
四、编写MapReduce程序
用户需要编写的三个部分:Mapper、Reducer、Driver(提交MR程序)。
4.1 以WordCount为例:
1. 编写Mapper
// 注意:hadoop1.0版本中是mapred下包,hadoop2.0是mapreduce下的包
import org.apache.hadoop.mapreduce.Mapper;
// 继承Mapper父类,泛型为输入和输出的<K, V>;并重写父类的map方法
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
/**
* 每行文本都会执行一次map方法.
*
* @param key 文本偏移量.
* @param value 一行文本.
* @param context 上下文对象.
* @throws IOException .
* @throws InterruptedException 当阻塞方法收到中断请求时抛出.
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split("\\s+"); // 拆分一行中的单词
for (String word : words) {
context.write(new Text(word), new IntWritable(1)); // 输出一个<K, V>
}
}
}
2. 编写Reducer
// 继承Reducer类,输入的<K, V>类型为map端输出<K, V>类型
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
/**
* 相同的key只会执行一次reduce方法
*
* @param key map端输出的key
* @param values 相同key的value集合
* @param context 上下文对象
* @throws IOException .
* @throws InterruptedException .
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
// 当前的 key出现了多少次
int count = 0;
// values中的数据是反序列化过来的,最好不要直接使用values中的bean
for (IntWritable value : values) {
count += value.get();
}
context.write(key, new IntWritable(count)); // 输出
}
}
3. 编写Driver
// Driver的作用是将这个Mapper和Reducer程序打包成一个Job,并提交该Job
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// 不需要为 conf设置HDFS等参数,因为conf会调用系统默认的配置文件,
// 所以这个mr程序在哪里运行就会调用哪里的配置文件,在集群上运行就会使用集群的设置文件。
Configuration conf = new Configuration();
// 删除输出文件,或者手动删除
// FileHelper.deleteDir(args[1], conf);
// 根据配置文件实例化一个 Job,并取个名字
Job job = Job.getInstance(conf, "MyWordCount");
// 设置 Jar的位置
job.setJarByClass(WordCountDriver.class);
// 设置 Mapper运行类,以及输出的key和value的类型
job.setMapperClass(WordCountMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 设置 Reducer的运行类,以及输出的key和value的类型
job.setReducerClass(WordCountReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 设置分区(可以不用设置)
// 当设置的分区数大于实际分区数时,可以正常执行,多出的分区为空文件;
// 当设置的分区数小于实际分区数时,会报错。
job.setNumReduceTasks(4);
// 如果设置的 numReduceTasks大于 1,而又没有设置自定义的 PartitionerClass
// 则会调用系统默认的 HashPartitioner实现类来计算分区。
job.setPartitionerClass(WordCountPartitioner.class);
// 设置combine
job.setCombinerClass(WordCountCombiner.class);
// 设置输入和输出文件的位置
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// 提交任务,等待执行结果,参数为 true表示打印信息
boolean result = job.waitForCompletion(true);
// 根据 job的返回值自定义退出
System.exit(result?0:1);
}
}
4. 运行
- 如果在Hadoop集群上运行还需要将这个project打包成jar包,所以一般是先在windows上运行调试。
- 由于要从命令行输入input和output参数,所以这里配置一下输入和输出的位置。
五、MapReduce的主要执行流程
- job.waitForCompletion(true):将这个MapReduce任务(Job)提交,默认是提交到本地运行;部署到集群时,是提交给YARN运行。
- map():在父类Mapper的run()方法中会调用子类重写的map()方法。输入文件的每一行都会调用一次map()方法,map()方法的参数中:key为当前输入行的偏移量,LongWritable类型;value为当前输入行的数据,Text类型;context为上下文对象。父类Mapper是一个泛型类,泛型的类型表示map()方法输入和输出的<K, V>类型,子类在继承时要传入实际输入输出的<K, V>类型。map()使用context.write(k, v)来输出数据到shuffle阶段的环形缓冲区。
- shuffle阶段简述:shuffle阶段起到承上启下的作用;从接收map()方法的输出,到执行reduce()方法之前都属于shuffle阶段。shuffle接收map()输出<K,V>并通过K计算出分区号,然后与元数据一起写入环形缓存区;环形缓冲区溢写时会将数据排序并写入小文件,然后归并成一个大的分区文件。一个ReducerTask主机会到所有MapTask主机上拉取对应的分区文件,归并所有分区文件后会对相同的key进行合并,再执行reduce方法。
- reduce():在父类Reducer的run()方法中会调用子类重写的reduce()方法。相同的key只会调用一次reduce()方法,reduce()方法的参数中:key为相同key合并后的第一个key,与map()的输出key类型相同;values为相同key的value列表,类型是Iterable<map()的输出value类型>。与Mapper类类似,子类在继承Reducer时输入的<K, V>类型是Mapper输出的<K, V>类型、Reducer输出的<K, V>类型是context.write(K, V)中<K, V>的类型。reduce中的context.write(K, V)最终会写入到输出文件中,就是这次MapReduce的结果。
7,MapReduce基础的更多相关文章
- [Hadoop in Action] 第4章 编写MapReduce基础程序
基于hadoop的专利数据处理示例 MapReduce程序框架 用于计数统计的MapReduce基础程序 支持用脚本语言编写MapReduce程序的hadoop流式API 用于提升性能的Combine ...
- Hadoop 综合揭秘——MapReduce 基础编程(介绍 Combine、Partitioner、WritableComparable、WritableComparator 使用方式)
前言 本文主要介绍 MapReduce 的原理及开发,讲解如何利用 Combine.Partitioner.WritableComparator等组件对数据进行排序筛选聚合分组的功能.由于文章是针对开 ...
- MapReduce(一) mapreduce基础入门
一.mapreduce入门 1.什么是mapreduce 首先让我们来重温一下 hadoop 的四大组件:HDFS:分布式存储系统MapReduce:分布式计算系统YARN: hadoop 的资源调度 ...
- MongoDB:MapReduce基础及实例
背景 MapReduce是个非常灵活和强大的数据聚合工具.它的好处是可以把一个聚合任务分解为多个小的任务,分配到多服务器上并行处理. MongoDB也提供了MapReduce,当然查询语肯定是Java ...
- MapReduce基础知识
hadoop版本:1.1.2 一.Mapper类的结构 Mapper类是Job.setInputFormatClass()方法的默认值,Mapper类将输入的键值对原封不动地输出. org.apach ...
- MapReduce基础
这篇文章翻译自Yahoo的Hadoop教程,很久之前就看过了,感觉还不错.最近想总结一下以前学的东西,看到现在关于Hadoop的中文资料还比较少,就有了把它翻译出来的想法,希望能帮助到初学者.这只是Y ...
- hadoop mapreduce 基础实例一记词
mapreduce实现一个简单的单词计数的功能. 一,准备工作:eclipse 安装hadoop 插件: 下载相关版本的hadoop-eclipse-plugin-2.2.0.jar到eclipse/ ...
- Hadoop系列-MapReduce基础
由于在学习过程中对MapReduce有很大的困惑,所以这篇文章主要是针对MR的运行机制进行理解记录,主要结合网上几篇博客以及视频的讲解内容进行一个知识的梳理. MapReduce on Yarn运行原 ...
- MapReduce 基础学习
什么是MapReduce? mapreduce 是一种软件框架 mapreduce job将任务分解为独立的块儿到不同的map task,进行并行处理: map任务输出会做相应的排序处理,并作为r ...
随机推荐
- 计算机BIOS的简单设置(要安装Linux需关闭Security Boot选项)
计算机BIOS的简单设置(要安装Linux需关闭Security Boot选项) 发布时间:2016-12-07 22:46:19来源:linux网站作者:乐百川 BIOS是什么 BIOS全称是基本输 ...
- Jump Game (Medium)
主要有两种思路: 一. 本题只需要判断能否到达最后一个数,那么可以采用贪心策略,到达某个位置i后,在直接在这个位置的基础上走nums[i]步,主要保证能一直前进,就能达到终点: 那么,什么时候才不能一 ...
- spring xml 注入 map 时 map 标签报错
如图所示: 在XML配置文件中并没有问题,问题出在实体类,在类中属性 maps 用 Map定义即可,用HashMap定义就会出现如上错误 K-I-N-G-D-O-M
- Query对象与DOM对象之间的转换
什么是jQuery对象? ---就是通过jQuery包装DOM对象后产生的对象.jQuery对象是jQuery独有的,其可以使用jQuery里的方法. 比如: $("#test") ...
- IOS下的safari下localStorage不起作用的问题
我们的一个小应用,使用百度地图API获取到用户的坐标之后用localStorage做了下缓存,测试上线之后有运营同学反馈页面数据拉取不到, 测试的时候没有发现问题,而且2台相同的iphone一台可以一 ...
- [转载] 自定义标签,jsp调用java类
自己懒得做笔记,借用一下. 之前例子已经写好了,由于时间关系一直没有发布,这次带来的是关于taglib中的<tag>的基本功能已经介绍完毕了,在taglib中我们发现有一个标签叫做< ...
- NBA球星的生意经 个人流量化之路
个人流量化之路" title="NBA球星的生意经 个人流量化之路"> 在国人欢天喜地的庆祝新春佳节之时,大洋彼岸也在进行着让全球篮球迷为之"着魔&quo ...
- mysql视图、事务、触发器、索引
视图 什么是视图 ? 一个查询语句的结果是一张虚拟表,将这种虚拟表保存下来,它就变成了一个视图. 为什么要用视图? 当频繁需要用到多张表的连表结果,你就可以事先生成好视图,之后直接调用即可,避免了反复 ...
- 分布式ID生成策略 · fossi
分布式环境下如何保证ID的不重复呢?一般我们可能会想到用UUID来实现嘛.但是UUID一般可以获取当前时间的毫秒数再加点随机数,但是在高并发下仍然可能重复.最重要的是,如果我要用这种UUID来生成分表 ...
- springboot 多数据源之错误 HikariPool-1 - jdbcUrl is required with driverClassName.
数据源连接报错: 之前在1.5.7的版本的时候用该数据源配置没问题,看如下所示 springboot1.5.7配置多数据源: datasource.master.url=jdbc:mysql://lo ...