MapReduce
MapReduce
为什么要学习MapReduce
单机版:内存受限,磁盘受限,运算能⼒受限 ⽽⼀旦将单机版程序扩展到集群来分布式运⾏,将极⼤增加程序的复杂度和开 发难度 引⼊MapReduce框架后,开发⼈员可以将绝⼤部分⼯作集中在业务逻辑的开发 上,⽽将分布式计算中的复杂性交由框架来处理
MapReduce简介
MapReduce是Apache Hadoop项⽬的⼀个核⼼模块 MapReduce是⼀个运⾏在hdfs上的分布式运算程序的编程框架,⽤于⼤规模数 据集(⼤于1TB)的并⾏运算 概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式 编程语⾔⾥借来的,还有从⽮量编程语⾔⾥借来的特性 它极⼤地⽅便了编程⼈员在不会分布式并⾏编程的情况下,将⾃⼰的程序运⾏ 在分布式系统上
MapReduce优缺点
优点
1. MapReduce易于编程 它简单的实现⼀些接⼝,就可以完成⼀个分布式程序,这个程序可以分布到⼤量的 廉价的pc机器上运⾏。也就是说你写⼀个分布式程序,跟写⼀个简单的串⾏程序是⼀模 ⼀样的。就是因为这个特性使的MapReduce编程变得⾮常流⾏。 2. 良好的扩展性 当你的计算资源得不到满⾜的时候,你可以简单的通过增加机器来扩展它的计算能 ⼒ 3. ⾼容错性 MapReduce的设计初衷就是使程序能够部署在廉价的pc机器上,这就要求它具有 很⾼的容错性。⽐如⼀个机器挂了,它可以把上⾯的计算任务转移到另⼀个节点上运 ⾏,不⾄于这个任务运⾏失败,⽽且这个过程不需要⼈⼯参与,⽽完全是由hadoop内 部完成的。 4. 适合PB级以上海量数据的离线处理
缺点
1. 不适合实时计算 MapReduce⽆法做到像Mysql那样做到毫秒或者秒级的返回结果 2. 不适合流式计算 流式计算的输⼊数据是动态的,⽽MapReduce的输⼊数据集是静态的,不能流态变 化。这是MapReduce⾃身的设计特点决定了数据源必须是静态的。 3. 不适合DAG(有向图)计算 多个应⽤程序存在依赖关系,后⼀个应⽤程序的输⼊为前⼀个应⽤程序的输出,在 这种情况下,MapReduce并不是不能做,⽽是使⽤后每个MapReduce作业的输出结果都 会写⼊到磁盘,会造成⼤量的磁盘IO,导致性能⾮常低下。
MapReduce核⼼思想
1.MapReduce设计的⼀个理念是“计算向数据靠拢”(移动计算),⽽不是“数据向计 算靠拢”(移动数据) 2.将⽤户编写的业务逻辑代码和⾃带默认组件整合成⼀个完整的分布式运算程序,移 动到有数据存储的集群节点上,⼀是可以减少节点间的数据移动开销。⼆是在存储节 点上可以并⾏计算,⼤⼤提⾼计算效率问题。 因为移动数据需要⼤量的⽹络传输开销,尤其是在⼤规模数据环境下,这种开销 尤为惊⼈,所以移动计算要⽐移动数据更加经济。 3.MapReduce⼀个完整的运算分为Map和Reduce两个部分。Map会处理本节点的原 始数据,产⽣的数据会临时存储到本地磁盘。Reduce会跨节点fetch属于⾃⼰的数 据,并进⾏处理,产⽣的数据会存储到HDFS上。
MapReduce的阶段分类
第⼀阶段
第⼀阶段,也称之为Map阶段。这个阶段会有若⼲个MapTask实例,完全并⾏运 ⾏,互不相⼲。每个MapTask会读取分析⼀个InputSplit(输⼊分⽚,简称分⽚)对应 的原始数据。计算的结果数据会临时保存到所在节点的本地磁盘⾥。
数据扭转
该阶段的编程模型中会有⼀个map函数需要开发⼈员重写,map函数的输⼊是⼀个 <key,value>对,map函数的输出也是⼀个<key,value>对,key和value的类型需要开发 ⼈员指定。
第⼆阶段
第⼆阶段,也称为Reduce阶段。这个阶段会有若⼲个ReduceTask实例并发运⾏,互 不相⼲。但是他们的数据依赖于上⼀个阶段的所有maptask并发实例的输出。⼀个 ReudceTask会从多个MapTask运⾏节点上fetch⾃⼰要处理的分区数据。经过处理 后,输出到HDFS上。
数据扭转
该阶段的编程模型中有⼀个reduce函数需要开发⼈员重写,reduce函数的输⼊也是 ⼀个<key,value>对,reduce函数的输出也是⼀个<key,value>对。这⾥要强调的 是,reduce的输⼊其实就是map的输出,只不过map的输出经过shuffle技术后变成 了<key,List>⽽已。
注意: MapReduce编程模型只能包含⼀个map阶段和⼀个reduce阶段,如果⽤户的 业务逻辑⾮常复杂,那就只能多个MapReduce程序,串⾏运⾏。
MapReduce编程规范
⽤户编写的程序分为3个部分:Mapper、Reducer、Driver(提交mr程序的客户 端)
Mapper部分
1. ⾃定义类,继承Mapper类型 2. 定义K1,V1,K2,V2的泛型(K1,V1是Mapper的输⼊数据类型,K2,V2是Mapper的 输出数据类型) 3. 重写map⽅法(处理逻辑)
注意:map⽅法,每⼀个KV对都会调⽤⼀次。
Reducer部分
1. ⾃定义类,继承Reducer类型 2. 定义K2,V2,K3,V3的泛型(K2,V2是Reducer的输⼊数据类型,K3,V3是Reducer 的输出数据类型) 3. 重写reduce⽅法的处理逻辑
注意: reduce⽅法,默认按key分组,每⼀组都调⽤⼀次。
Driver部分
整个程序需要⼀个Driver来进⾏提交,提交的是⼀个描述了各种必要信息的job对 象,如下
1. 获取Job对象 2. 指定驱动类 3. 设置Mapper和Reducer类型 4. 设置Mapper的输出K2、V2的类型(如果类型和K3,V3相同,可省略) 5. 设置Reducer的输出K3、V3的类型 6. 设置Reduce的个数(默认为1) 7. 设置Mapper的输⼊数据的路径 8. 设置Reducer的输出数据的路径 9. 提交作业