WritableComparable 排序
排序是 MapReduce 框架中最重要的操作之一。MapTask 和 ReduceTask 均会对数据按照
key 进行排序。该操作属于 Hadoop 的默认行为。任何应用程序中的数据均会被排序,而不
管逻辑上是否需要。默认排序是按照字典顺序排序,且实现该排序的方法是快速排序。
对于 MapTask,它会将处理的结果暂时放到环形缓冲区中,当环形缓冲区使用率达到
一定阈值后,再对缓冲区中的数据进行一次快速排序,并将这些有序数据溢写到磁盘上,
而当数据处理完毕后,它会对磁盘上所有文件进行归并排序。
对于 ReduceTask,它从每个 MapTask 上远程拷贝相应的数据文件,如果文件大小超过
一定阈值,则溢写磁盘上,否则存储在内存中。如果磁盘上文件数目达到一定阈值,则进
行一次归并排序以生成一个更大文件;如果内存中文件大小或者数目超过一定阈值,则进
行一次合并后将数据溢写到磁盘上。当所有数据拷贝完毕后,ReduceTask 统一对内存和磁
盘上的所有数据进行一次归并排序。
排序的分类有:
➢ 部分排序。MapReduce 根据输入记录的键对数据集排序。保证输出的每个文件内
部有序。
➢ 全排序。最终输出结果只有一个文件,且文件内部有序。实现方式是只设置一个
ReduceTask。但该方法在处理大型文件时效率极低,因为一台机器处理所有文
件,完全丧失了 MapReduce 所提供的并行架构。
➢ 辅助排序:(GroupingComparator 分组)。在 Reduce 端对 key 进行分组。应用
于:在接收的 key 为 bean 对象时,想让一个或几个字段相同的 key 进入到同一个
reduce 方法时,可以采用分组排序。
➢ 二次排序。在自定义排序过程中,如果 compareTo 中的判断条件为两个即为二次
排序。
自定义排序时,例如将 bean 对象做为 key 传输,需要实现 WritableComparable 接口
重写 compareTo 方法,就可以实现排序。
1. WritableComparable 排序操作案例(全排序与二次排序)
1) 案例描述
将 4.3.3 节序列化案例中得到的结果再次对总流量进行倒序排序。
2) 案例实现
a) 创建包 com.dh.mapreduce.writableComparable,将包 com.dh.mapreduce.
writable 中编写的 FlowBean、FlowMapper、FlowReducer、FlowDrier 四个类复
制到该包中。
b) 将类 FlowBean 修改,实现 WritableComparable 接口,并且重写 compareTo
方法,代码如下:
@Override
public int compareTo(FlowBean flowBean) {
//按照总流量的倒叙进行排序
if(this.sumFlow>flowBean.sumFlow){
return -1;
}else if(this.sumFlow<flowBean.sumFlow){
return 1;
Commented [丁 1]: mapreduce 只对 key 排序
但是此时 key 是手机号 咋办?
现在把 FlowBean 作为 key
手机号作为 value
这样是不是就可以对流量进行排序了
自定义的 FlowBean 是要做序列化的 -已解决
FlowBean 必须能比较大小,否则不能排序的
如果需要将自定义的 bean 放在 key 中传输,则
还需要实现 Comparable 接口
,因为 MapReduce 框中的 Shuffle 过程要求对
key 必须能排序。详见后面排序案例。
Commented [丁 2]: 注意要有泛型
public class FlowBean
implements
WritableComparable<FlowBean>