1.MapReduce中的Combiner
1. Combiner 是 MR 程序中 Mapper 和 Reducer 之外的一种组件 2. Combiner 组件的父类就是 Reducer 3. Combiner 和 reducer 的区别在于运行的位置 4. Combiner 是在每一个 maptask 所在的节点运行 ; 5. Combiner 的意义就是对每一个 maptask 的输出进行局部汇总,以减小 网络传输量 。 6. Combiner 能够应用的前提是不能影响最终的业务逻辑,此外, Combiner 的输出 kv 应该跟 reducer的输入kv 类型要对应起来。 举例说明 假设一个计算平均值的 MR 任务 Map 阶段 2 个 MapTask MapTask1 输出数据: 10,5,15 如果使用 Combiner:(10+5+15)/3=10 MapTask2 输出数据: 2,6 如果使用 Combiner:(2+6)/2=4 Reduce 阶段汇总 ( 10+4 ) /2=7 而正确结果应该是 ( 10+5+15+2+6 ) /5=7.6 7.自定义 Combiner 实现步骤 自定义一个 Combiner 继承 Reducer ,重写 Reduce 方法 在驱动 (Driver) 设置使用 Combiner (默认是不适用 Combiner 组件) 直接使用Reducer作为Combiner组件来使用是可以的!! 2.MapReduce中的排序 排序是 MapReduce 框架中最重要的操作之一。 MapTask 和 ReduceTask 均会对数据按照 key 进行排序。该操作属于 Hadoop 的 默认 行为。任何应用程序中的数据均会被排序,而不管逻辑 上是否需要。默认排序是按照 字典顺序排序 ,且实现该排序的方法是 快速排序 MapTask 它会将处理的结果暂时放到环形缓冲区中,当环形缓冲区使用率达到一定阈值后,再对缓冲区中的数据进行一次快速排序,并将这些有序数据溢写到磁盘上, 溢写完毕后,它会对磁盘上所有文件进行归并排序。 ReduceTask 当所有数据拷贝完毕后, ReduceTask 统一 对内存和磁盘上的所有数据进行一次归并排序。 1. 部分排序 . MapReduce 根据输入记录的键对数据集排序。保证输出的每个 文件内部有序 。 2. 全排序 最终输出结果只有 一个文件 ,且文件内部有序。实现方式是只设置 - - 个 ReduceTask 。但该方法在 处理大型文件时效率极低,因为一 台机器处理所有文件,完全丧失了 MapReduce 所提供的并行架 构。 3. 辅助排序 : ( GroupingComparator 分组 ) 在 Reduce 端对 key 进行分组。应用于 : 在接收的 key 为 bean 对象时,想让一个或几个字段相同 ( 全部字段比较不相同) 的 key 进入到同一个 reduce 方法时,可以采用分组排序。 4. 二次排序 . 在自定义排序过程中,如果 compareTo 中的判断条件为两个即为二次排序。 3.自定义排序对象 1. 自定义对象作为 Map 的 key 输出时,需要实现 WritableComparable 接口,排序:重写compareTo()方法,序列以及反序列化方法 2. 再次理解 reduce() 方法的参数; reduce() 方法是 map 输出的 kv 中 key 相同的 kv 中的 v 组成一个集合调 用一次reduce() 方法,选择遍历 values 得到所有的 key。 3. 默认 reduceTask 数量是 1 个; 4. 对于全局排序需要保证只有一个 reduceTask!! 4.GroupingComparator GroupingComparator 是 mapreduce 当中 reduce 端的一个功能组件,主要的作用是决定哪些数据作为一组,调用一次reduce 的逻辑,默认是每个不同的 key ,作为多个不同的组,每个组调用一次 reduce 逻辑,我们可以自定义 GroupingComparator实现不同的key作为同一个组 ,调用一次 reduce 逻辑。 同一个分区的数据会调用同一个GroupingComparator,通过重写compare()方法可以定义哪些数据作为同一组key,同一组key调用一次reduce。如图 定义00001和00003作为同一组key,则00001和00003一共只会调用一次reduce 未定义 定义00001和00003作为同一组key时输出: OrderBean{orderId='0000001', price=222.8} OrderBean{orderId='0000003', price=232.8} 定义 定义00001和00003作为同一组key时输出: OrderBean{orderId='0000001', price=222.8}