技术背景
- 详见 HDFS 分布式文件存储服务(一) 概念介绍
设计目的
- 为了解决[海量数据的并行计算问题]
设计思想
- 通过分布式系统将计算任务拆分给每个子节点,由各个子节点进行子任务计算,以此来解决并行计算问题
最后将计算结果返回
技术本质
- mapreduce是一种根据初始程序设计,用来解决分布式环境下的并行计算问题,一个拥有自己特定的计算逻辑的一段程序代码。并不具有自己单独的进程,设计运行在yarn集群上
核心特性
- 适合数据复杂度运算
- 不适合算法复杂度运算
- 即简单算法的大数据量运算
任务角色
Maptask
- 概念:map阶段任务
- 内容: map阶段包括 Input,map,map端的shuffle几个小阶段
- 补充:
一个split切片对应一个maptask任务,即默认一个block块一个maptask;
通过 Math.max(minSize,Math.min(maxSize,blockSize)) 规则决定;
minSize分片最小默认是0,maxSize分片最大默认256,
blockSize默认128,所以默认规则一个block块一个maptask
Input
- 概念: 数据输入
- 职责:
1.文件存储在hdfs上,Input将block数据块切片为split,
默认一个block块一个split切片, 实现方法: ==>textinputformat类的getsplits()
2.将split切片转换成key value键值对; ==> recordReader类的nextKeyValue() - 处理逻辑:
转换逻辑是recordreader决定的,默认读取器是Textinputformat.linerecordreader,将文件的每一行转换为一个key value对返回 - 输入格式:
1.inputformat是所有输入格式的父类,是抽象类;默认TextInputFormat
2.子类实现:FileInputFormat,DBInputFormat,TableInputformat
3.孙子类实现:TextInputFormat extends FileInputFormat extends InputFormat - 输出格式:
<key value>键值对,key value 可为自定义的数据类型 - 意义:
1.拆分: 格式化数据方便map进行处理;
2.输入: 输入需要进行maptask的数据 - 补充:
自定义的数据类型需要实现序列号接口,若无自定义比较器,则需要实现writablecomparable接口
Map
- 职责: 负责map端的处理逻辑,
- 实现: 需要继承mapper类,重写map方法;
- 意义: 映射:指定后续需要处理的key和value的关系,根据业务逻辑的预处理
- 处理逻辑: input输出的每一条key value数据就会调用一次map方法
- 输入格式: <key value>键值对,key value 可为自定义的数据类型
- 输出格式: <key value>键值对,key value 可为自定义的数据类型
Map端Shuffle
- 内容:map端shuffle又可以细分为spill溢写,partition分区排序,merge合并排序,combiner, compress
Spill溢写
- 职责: 将maptask的任务输出逐渐从内存中写到缓存小文件中
- 意义: 避免maptask处理结果在内存中持续积累,造成内存溢出
- 处理逻辑:在内存中存在100M的环形缓冲区,当maptask的任务输出达到80%的时候,就触发了溢写的条件,开始准备溢写,此时会经历分区,排序的流程,最终写到缓存小文件中,因为80%缓冲区会造成,触发,写入,触发,写入...断续流程,所以最终生成很多个分区内有序的小文件
- 输入格式:maptask的输出,即key value>键值对
- 输出格式:多个分区内有序的缓存小文件
Partition分区排序
- 职责:
1.将触发达到溢写条件的数据,进行打标签--分区;
2.分区完之后进行分区内排序,写入到小文件中 - 意义:
1.分区:确定该条数据该由哪个reduce任务进行处理。
2.排序: 小数据先进行局部排序,减轻后续流程负载压力 - 处理逻辑:
1.分区:默认按照key的hash值对reduce个数取余,本质是打标签,可以通过实现partitionner分区器,重写getpartition()方法来自定义分区规则。
2.排序: 在进行分区后的小数据中使用【快速排序】,使得分区后的数据局部有序 - 输入格式:maptask的输出,即key value>键值对
- 输出格式:多个分区内有序的缓存小文件
- 补充:
发生在spill触发之后,这个才是实际的spill输出格式,就是说spill包括partition和sort
Merge合并排序
- 职责:
1.当maptask完成时,缓冲区内容flush后,才开始merge。将spill溢写出来的各个缓存小文件合并成为一个大文件,
2.merge同时将各个小文件中相同分区的数据再次进行【归并排序】 - 意义:
1.合并: 一个maptask对应一个map文件输出,
- 排序: 小文件合并到大文件进行排序,减轻后续流程负载压力
- 处理逻辑:
1.合并:
2.排序:优先使用比较器,若无比较器,则使用自定义数据的compareto方法或者按照字典升序 - 输入格式:多个缓存小文件
- 输出格式:一个缓存大文件
Combiner
- 职责:
在map端先做一次聚合。Shuffle过程中的另外一个功能,默认是关闭,需要自己手动设置该功能来启用 - 意义:
利用maptask的个数远大于reduce的个数,将聚合的逻辑由每个Map完成一部分,最后再由Reduce做最终的聚合,减轻Reduce的负载 - 处理逻辑: 一般使用reduce的处理逻辑
- 输入格式:一个缓存大文件
- 输出格式:一个经过初次聚合的大文件
Compress
- 概念:压缩,减少网络传输,本章后面会继续介绍
ReduceTask
- 概念:Reduce阶段任务
- 内容: Reduce阶段包括Reduce端的Shuffle,Reduce,output三个小阶段
- 补充:
一个分区对应一个reduceTask,即默认只有一个reducetask;job.setNumberReduceTask()设置reduce个数
Reduce端Shuffle
- 内容:Reduce端的Shuffle也分为两个小阶段,排序,分组;
合并排序
- 职责:
通过http协议,从各个节点中将maptask输出的文件中属于自己分区的数据拉取过来,因为各个文件是局部有序,在合并是需要重新【归并排序】, - 意义: 组织处理并提供reduce端处理数据的输入
- 处理逻辑:
1.合并:
2.排序:优先使用比较器,若无比较器,则使用自定义数据的compareto方法或者按照字典升序 - 输入格式:各个节点中局部有序的数据
- 输出格式:只属于该reducetask处理的全局有序的数据
分组
- 职责: 将reduce拉取的全局有序的数据进行聚合,分组后的每一条数据调用一次reduce方法
- 意义: 聚合,便于reduce方法使用
- 处理逻辑:相同key放入同一组键值对,key为键,同一组的value放入同一个迭代器作为值
- 输入格式: 未分组的数据
- 输出格式: 经过分组的数据
Reduce
- 职责: 负责处理reduce端的逻辑,
- 实现: 需要继承reducer,重新reduce方法
- 意义: 统计:指定如何处理key和value的关系,根据业务逻辑进行处理
- 处理逻辑:自定义
- 输入格式:
- 输出格式:
Output
将reduce处理完的数据输出到对应的output,默认将结果保存在hdfs上,并且key和value以制表符分隔