一、MapReduce概述
1.1 MapReduce定义
MapRedrce是一个分布式运算程序的编程框架,是用户开发“基Hadoop的数据分析应用”的核心框架。
MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一-个Hadoop集群上。
1.2 认识MapReduce
MapReduce源于Google的一篇论文,将数据处理过程分为Map(映射)和Reduce(化简)两步
- 特点:
- Hadoop MapReduce运行在YARN之上,由YARN提供了集群扩展性和容错性等特性;
- 开发较方便:用户通过Hadoop提供的MapReduce框架即可完成编程;
- Hadoop MapReduce更面向底层,编程方式较为复杂,使用Spark中提供的函数式编程也可快速实现MapReduce程序;
- Hadoop MapReduce直接基于HDFS,速度不如内存计算快,数据密集型任务是其真正的优势。
数据密集型任务
- 面对PB级海量的数据,很难将数据全部放入内存进行计算;
- Hadoop MapReduce基于HDFS执行计算,可用于前期的大规模数据清洗、统计、转换以及特征提取;
- 可使用Hive和Pig快速编写基于MapReduce的查询程序。
1.3 MapReduce的缺点
- 不擅长实时计算
MapReduce无法像MySQL-样,在毫秒或者秒级内返回结果。 - 不擅长流式计算
流式计算的输入数据是动态的,而MapReduce的输入数据集是静态的,不能动态变化。这是因为MapReduce自身的设计特点决定了数据源必须是静态的。 - 不擅长DAG (有向图)计算
多个应用程序存在依赖关系,后一个应用程序的输入为前一个程序的输出。在这种情况下,MapReduce并不是不能做,而是使用后,每个MapReduce作业的输出结果都会写入到磁盘,会造成大量的磁盘IO,导致性能非常的低下。
二、MapReduce编程思想
Map和Reduce来源于LISP和其他函数式编程语言中的古老的映射和化简操作。
- MapReduce操作数据的最小单位是键值对
编程步骤:
1、将数据分片,并将每个数据切片分别输入到map函数中
2、map函数计算处理输入的子数据,并产生键值对作为中间结果输出。
映射: 将有用的数据映射(map)到键值对上
3、框架会将所有节点的这些中间结果键做聚合处理,并将键相同的数据分发给reduce函数处理
化简: 将各个map输出的键合在一起,遇到相同的键,合并成一个键值对,它们的值做成数组并排序;这样Key就减少(reduce)了
4、reduce函数处理这些键和对应的值的集合,再产生新的键值对作为最终输出
化简: 处理合并后的键值对,将键的value(数组)提取出来进行计算,进一步减少(reduce) value
算法设计思想
- 分布式程序与单机程序不同之处:数据和程序会被分发到多个节点中,一个节点不能处理全部数据
- 一个Map或Reduce执行在YARN中的一个Container中,该Container由NM的ApplicationMaster管理
- Container被分配多少资源、何时分配、分配到哪个NM中,由NM的ApplicationMaster申请,RM的Scheduler根据调度算法得到,并返回给ApplicationMaster
- 用户程序执行后,会被复制到所有Container中执行,即所有Container中执行的程序都是一样
- 单机思想:代码要考虑到对所有的数据的处理
- 分布式/并行思想:写代码时须考虑到本代码是针对数据片段编写的,且须适用于所有的数据片段
三、Word Count 程序执行过程分析
Word Count程序是MapReduce的经典入门实例,用以统计文本中各个词汇的出现次数(词频矩阵)。
图中主要分为Split、Map、Shuffle和Reduce阶段,每个阶段的作用如下:
- Split 阶段:首先大文件被切分成多分,假设这里分成了2份,每一行代表一份
- Map 阶段:解析出每个单词,并在后边记上数字 1。
- Shuffle 阶段:将每一份中的单词分组到一起,并默认按照字母进行排序。
- Reduce 阶段:将相同的单词进行累加。
- 输出结果
四、MapReduce框架
主类声明:
public class WordCountApp extends Configured implements Tool
需要继承至:org.apache.hadoop.conf.Configured
对作业的定义和管理,并实现接口 org.apache.hadoop.util.Tool
定义了Job入口
4.1 常用数据序列化类型
4.2 Map实现
map由Mapper的子类实现
- 具体的map方法须重写Mapper类的map方法
- MR框架会自动创建map实例并执行,且会将读取到的输入文本拆分后由value属性传入。
- 使用StringTokenizer类将value文本拆分为词汇,遍历词汇,并将词汇和其出现次数组合成键值对写入上下文(MR由框架传入的一个对象,专门用于保存计算过程中的数据)
4.3 Reduce实现
reduce由Reducer的子类实现
- 具体的reduce方法须重写Reducer类的reduce方法
- MR框架会自动创建reduce实例并执行,且会将分配给该reduce的键值对由key和val变量传入。
- 将val转为Iterator序列后遍历之,将其数量相加后输出到Context中,MR框架会自动将输出值写入到输出目录中
4.4 Run方法实现
- 实例化Job
- 注入作业主类
job执行的主类是什么 - 注入Map类
执行map逻辑的类(Mapper的子类) - 注入Reduce
执行reduce逻辑的类(Reducer的子类) - 注入输入类并获取输入文件的路径
TextInputFormat类:识别执行命令中的输入路径字串并写入 - 注入输出类并获取输出目录的路径
TextOutputFormat类:识别执行命令中的输出路径字串并写入
开始执行作业并等待执行完毕
4.5 MapReduce内部运行过程
- MapReduce内部运行过程:
• InputData:HDFS中输入的数据
• InputSplit:数据分片,每个map操作一个InputSplit
• InputFormat:负责读取InputSplit和执行键值对拆分
• Mapper:收到InputFormat后的键值对,执行map过程
• Combiner:对map过程的键值对进行一次处理以减少输出至Reducer的数据量,相当于map本地的reduce
• Partition:确定map的输出键和reduce的映射关系, Partition前有一个Barrier(完毕后才能进入Reducer同步障),保证所有Mapper执行。
• Shuffle:将map的输出键传输到指定的reduce中(reduce主动拉取),一个键对应一个reducer
• Sort:将传输给Reduce的键值排序并组合成序列
• Reducer:执行reduce过程
• OutputFormat:负责Job的输出,输出至HDFS
Barrier同步障: