MapReduce用于处理海量数据计算,由谷歌论文而来,从论文角度来讲是一种思想,从技术角度来讲。是一种计算框架
1 MR代码规范1.1 Mapper类
主要设计业务逻辑要什么输出
1.用户定义的Mapper类要继承父类
2.Mapper业务逻辑写在map()方法
3.Mapper输入数据是泛型KV对的形式,输出也是
Key 是偏移量,value 是值(内容)
4.Map()方法对每个
在WordCount中一个
前两点和Mapper通用:要继承父类、重写reduce方法
1.输入数据类型对应Mapper输出类型
2.对每一组相同k的
有几个k就reduce几次
reduce()方法 参数如下:
概念:
类似一种八股文的写法:
2 MR序列化MR 序列化类型都是对象!
用自己的序列化类型原因是如下,紧凑、快速、互操作性高
序列化的作用:主要用于不同服务器传输(知识点可看图和CG笔记)
自定义反序列化1、implements Writeable接口
2、重写空参构造方法
public 类名(){}
3、重写序列化和反序列化方法(顺序要求一样)
4、重写tostring方法
---------------------------------------------------------------------------------------------------------------------------------
3 MR框架原理 MR工作流程并行度
MapTask数量:切片数量影响(切片数量影响MapTask数量),可通过公式修改切片大小,本地32m,读取方式不同比如TextInputFormat、NLineInputFormat也会影响切片的情况
ReduceTask数量:影响分区数量(ReduceTask影响分区数量)
drive:job.setNumReduceTask(x);
如果分区不是1,先判断ReduceNum不大于1则不执行分区。
FileInputFormat(文件输入)后,可以选择如何输入进Map()方法,继承关系如下:
默认的TextInputFormat调用里面的RecorderReader读取数据
Map
切片、提交JOB、Yarn打开MapTask、按照规则调用KV对(TextInputFormat、NLine等)、调用Map()方法
Mapper Shuffle
Partition分区、OutPutCollector写入环形缓冲区、溢写(之前进行快排Sort、可选Partition)、合并Merge归并排序
Reduce Shuffle
拉取相应分区文件 -> Merge归并排序 -> 分组(Group)
Reduce
集合聚合
Read -> Map->
Mapper Shuffle分区Partition -> OutPutCollector环形缓冲区 -> 溢写(溢写之前 快速排序Sort,可选合并Combine) -> 合并Merge归并排序 -> Reduce Shuffle(Copy)拉取相应分区文件 -> (Sort)Merge归并排序 -> (Reduce)分组(Group)
-> Reduce
环形缓冲区:默认100m,80%后溢写。一边存索引,一边存取真实的kv值。
Spill溢写:80%溢写,不100%的原因是因为溢写完成才空余RAM,这样得Map输出受限
·溢写完成后会产生两个文件,一个out文件,一个index文件,用于Reduce判断拉取数据
MapperShuffler排序:快排,排列对象是KV对的索引,按字典顺序
Combine合并:继承Reduce,慎重使用,如求中位数不一定一样了
Merge归并排序:对已经有序的序列进行排序最优。
·第一个是合并溢写的文件,第二个是合并不同分区拉过来的文件
Group分组:因为执行完毕后Key是排序的,一次读一组,values聚合成集合
·有一个辅助方法也可以实现排序(非系统默认实现的)
3.1 数据输入(InputForma) 3.1.1 FileInputFormat 切片机制切片是MAP的最小计算单元,一般等同于块大小。(Local模式一般为32m)
3.1.2 FileInputFormat机制源码解析 3.2 MR排序MR执行期间自动排序,执行完毕后,key都是有序的。(Key必须支持排序)
顺序:自然顺序
数字从小到大排序
字符串按字典顺序排序
排序种类
1.部分排序(默认排序)
每个分区的key是有序的,但分区和分区之间是无序的
2.全排序
最终输出只有一个文件,不仅每个分区的key是有序的,而且分区和分区也是有序的
·生产环境下慎用!文件量太大,聚合在一个reduce顶不住
3.二次排序
在自定义排序过程中,如果compareTo中判断条件为两个则为二次排序
·比如总流量相同,按上行流量再排序
怎么实现:
不管是原生的还是自定义的类型,只要这个类型用于key的类型,
一定要实现Comparable接口,若自定义排序则重写compareTo方法
默认排序规则:
1.原生的数据类型,已经实现Comparable接口,在源代码中重写comparaTo
方法提供默认排序规则
2.自定义数据类型,如果这个类型有作为key的需求,定义的时候必须继承实现
Comparable接口,重写comparaTo方法提供默认排序规则
4 ReduceJoin