MapReduce是什么?
MapReduce是Google的一项重要开源项目,他是一个用于大数据量计算的编程模型,对于大数据量计算,通常采用并行计算,但对大多说开发人员来说,自己完完全全实现一个并行计算的程序难度较大,MapReduce就是一种简化的并行计算编程模型。
MapReduce的特点
(1)易于编程,只需要简单的实现MapReduce提供的接口,就可以完成一个分布式程序。
(2)良好的扩展性,当计算机算力不够时,可以简单的通过增加机器来横向扩展算力。
(3)高容错性,当一台机器挂了,可以把上面的计算任务转移到另一个节点上,不至于程序运行失败,而这个过程完全不需要人工干涉,完全由Hadoop内部完成。
(4)能对PB级以上海量数据进行离线处理
MapReduce不擅长的场景
(1)实时计算,MapReduce无法像MySql一样,,在毫秒或秒级内返回结果。
(2)流式计算,流式计算输入的数据是动态的,而MapReudce的输入是静态的,不能动弹变化。
(3)DAG(有向图),多个应运程序存在依赖关系,后一个应用的输入是上一个程序的输出,在这个情况下MapReduce并不是不能做,而是每个MapReduce的输出结果都会保存在磁盘上,会造成大量磁盘IO,降低性能。
MapReduce编程模型
MapReduce由Map和Reduce两个阶段组成。
map函数以key/value作为输入,根据用户的代码输出新的key/value作为中间结果写入磁盘,MapReudce框架会自动将这些中间数据按照key值进行聚集(默认是对key进行Hash取模)的数据统一交给reduce。
reduce函数以key/value-list作为输入,根据用户代码映射产生新的一系列key/value,输出到HDFS上。
MapReduce执行流程
(1)MapReduce使用InputFormat模块,进行Map前的预处理,之后将文件切分成多个逻辑上的InputSplit(inputSplit 是 MapReduce 对文 件进行处理和运算的输入单位,只是一个逻辑概念,每个 InputSplit 并没有对文件进行实际 切割,只是记录了要处理的数据的位置和长度)。
(2)由于是逻辑上的分片,还需要通过RecordReder来读取分片上的是数据并把它们转成key/value形式的键值对输入给map。
(3)map会根据用户定义的映射规则,输出一系列新的key/value作为中间结果。
(4)为了让Redeuce更好的并行处理Map的结果,需要对Map进行一定的分区(Partition)、 排序(Sort)、合并(Combine)、归并(Merge)等操作,得到<key,value-list>形式的中间结果,再 交给对应的 Reduce 进行处理,这个过程称为 Shuffle。
(5)Reduce以一系列key/value-list作为输入,执行用户的逻辑代码,输出结果给OutputFormat。
(6)OutPutFormat模块在对结果进行校验,最终写到HDFS上。
Shuffle过程简述(只是简述更详细的原理以后真的需要在看学习吧..........)
(1)在 Map 端的 Shuffle 过程 Map 的输出结果首先被写入缓存,当缓存满时,就启动溢写操作,把缓存中的数据写入磁盘文件, 并清空缓存。当启动溢写操作时,首先需要把缓存中的数据进行分区,然后对每个分区的数据进行排序 (Sort)和合并(Combine,如果指定的话),之后再写入磁盘文件。每次溢写操作会生成一个新的磁盘文件, 随着 Map 任务的执行,在磁盘中就会生成多个溢写文件。在 Map 任务全部结束之前,这些溢写文件会 被归并(Merge)成一个大的磁盘文件,然后通知相应的 Reduce 任务来领取属于自己处理的数据。
(2)在 Reduce 端的 Shuffle 过程 Reduce任务从Map端的不同Map机器领回属于自己处理的那部分数据,然后对数据进行归并(Merge) 后交给 Reduce 处理。
MapReduce几个常用的操作
1.Combiner
Combiner是为了避免map任务和reduce任务之间无效的数据传输而设置的,Hadoop运行用户针对map任务的输出指定一个合并函数(我们可以吧Combiner看成在每个节点上先做一次reduce),可以减少传输到reduce的数据量,减少带宽和数据计算量。
2.Partitoner(自定义Partitoner可以通过继承Partitone,覆盖getPartitone方法实现)
在进行MapReduce计算时,有时需要把最终结果输出到不同的文件中,我们知道最终输出的数据来源于reducer,如果要输出多个文件,就要有多个reducer运行,reduce的数据来源于mapper,所以mapper要进行数据划分吧不同的数据分配给不同的reducer执行,
3.RecordReder
RecordReder定义了以怎样的方式读取分片中的数据。每读一条记录都会调用,系统默认的是LineRecordReder(按行读取),它是TextInputForMat对应的RecordReder。通过继承抽象类RecordReder,实现自定义InputFormat类,重写GreateRecordReder方法,配置job的InputFormat为自定义的InputFormat类。
后续代码图会贴上,睡觉。。