Shuffle 机制
Map 方法之后,Reduce 方法之前的数据处理过程称之为 Shuffle。
Partition 分区
1、问题引出
要求将统计结果按照条件输出到不同文件中(分区)。比如:将统计结果按照手机 归属地不同省份输出到不同文件中(分区)
2、默认 Partitioner 分区
默认分区是根据 key 的 hashCode 对 ReduceTask 个数取模得到的。用户没法控制哪 个 key 存储到哪个分区。
3、自定义 Partitioner 步骤
a、自定义类继承 Partitioner,重写 getPartitioner() 方法
b、在 Job 驱动中,设置自定义 Partitioner
c、自定义 Partition 后,要根据自定义 Partitioner 的逻辑设置相应数量的 ReduceTask
4、分区总结
a、如果 ReduceTask 的数量 > getPartition 的结果数,则会多产生几个空的输出文件 part-r-000xx;
b、如果 1 < ReduceTask 的数量 < getPartition 的结果数,则有一部分分区数据无处安 放,会 Exception;
c、如果 ReduceTask 的数量 = 1,则不管 MapTask 端输出多少个分区文件,最终结果都交给这一个 ReduceTask,最终也就只会产生一个结果文件 part-r-00000;
d、分区号必须从零开始,逐一累加。
5、案例分析
例如:假设自定义分区数为5,则
a、job.setNumReduceTasks(1); 会正常运行,只不过会产生一个输出文件
b、job.setNumReduceTasks(2); 会报错
c、job.setNumReduceTasks(6); 大于5,程序会正常运行,会产生空文件
WribatleComparable 排序
-
排序概述
排序是 MapReduce 框架中最重要的操作之一。
MapReduce 和 ReduceTask 均会对数据按照 key 进行排序。该操作属于 Hadoop 的默 认行为。任何应用程序中的数据均会被排序,而不管逻辑上是否需要。
默认排序是按照字典顺序排序,且实现该排序的方式是快速排序。
对于 MapTask,它会将处理的结果暂时放到环形缓冲区,当环形缓冲区使用率达到一定 阈值后,再对缓冲区中的数据进行依次快速排序,并将这些有序数据溢写到磁盘上,而当数 据处理完毕后,它会对磁盘上所有文件进行归并排序。
对于 ReduceTask,它从每个 MapTask 上远程拷贝相应的数据文件,如果文件大小超过 一定阈值,则溢写磁盘上,否则存储在内存中。如果磁盘上文件数目达到一定阈值,则进行 依次归并排序以生成一个更大文件;如果内存中文件大小或者数目超过一定阈值,则进行依 次合并后将数据一些到磁盘上。当所有数据拷贝完毕后,ReduceTask 统一对内存和磁盘上 的所有数据进行依次归并排序。
-
排序分类
1、部分排序
MapReduce 根据输入记录的键对数据集排序。保证输出的每个文件内部有序。
2、全排序
最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个 ReduceTask。但该方法在处理大型文件时效率极低,因为一台机器处理所有文件,完 全丧失了 MapReduce 所提供的并行架构。
3、辅助排序:(GroupingComparator 分组)
在 Reduce 端对 key 进行分组。应用于:在接收的 key 为 bean 对象时,想让一个 或几个字段相同(全部字段比较不相同)的 key 进入到同一个 reduce 方法时,可以采 用分组排序。
4、二次排序
在自定义排序过程中,如果 compareTo 的判断条件为两个即为二次排序。
-
自定义排序 WritableComparable 原理分析
bean 对象作为 key 传输,需要实现 WritabelComparable 接口重写 compareTo 方法, 就可以实现排序。
Combiner 合并
1、Combiner 时 MR 程序中 Mapper 和 Reducer 之外的一种组件。
2、Combiner 组件的父类就是 Reducer。
3、Combiner 和 Reducer 的区别在于运行的位置
Combiner 是在每一个 MapTask 所在的节点运行;
Reducer 是接收全局所有 Mapper 的输出结果;
4、Combiner 的意义就是对每一个 MapTask 的输出进行局部汇总,以减小网络传输量。
5、Combiner 能够应用的前提是不饿能影响最终的业务逻辑,而且,Combiner 的输出 kv 应 该跟 Reducer 的输入 kv 类型要对应起来。
错误案例:
Mapper Reducer
3 5 7 -> (3+5+7)/3=5 (3+5+7+2+6)/5=5 不等于 (5+4)/2=9/2
2 6 -> (2+6)/2=4
6、自定义 Combiner 实现步骤
a、自定一个 Combiner 继承 Reducer,重写 Redcue 方法
b、在 Job 驱动类中设置:
job.setCombinerClass(WordCountCombiner.class);