MapReduce实现二次排序

        默认情况下,Map输出的结果会按照key进行排序,但在实际的应用中,有时间我们不仅要对key进行排序,同时还要对value进行排序,这时候就要用到mapreduce中的二次排序。
 

一、  二次排序原理分析

        我们对二次排序分为以下几个阶段:
(1)Map起始阶段
        在Map阶段,通过job.setInputFormatClass()定义的InputFormat,将输入的数据集切分成小的split,同时InputFormat提供一个RecordReader的实现。RecordReader会将文本的行号最为Key,该行的内容作为Value,这也是Map的输入数据类型为<LongWritable, Text>的原因。接着会调用自定义的map方法,将读取到的<key, value>键值对输入给map方法。
(2)Map的最后阶段
        在Map的最后阶段,会先调用job.setPartitionerClass()对Mapper的输出结果进行分区,每个分区会映射到一个Reducer。在每个分区内,又会调用job.setSortComparatorClass()设置的key的比较函数类排序。这本身就是一个二次排序,如果没有通过job.setSortComparatorClass()设置key的比较函数类,则会使用key实现的compareTo()方法。
(3)Reducer阶段
        在Reducer阶段,自定义的reduce方法接收所有映射到这个reduce的map的输出,之后调用job.setSortComparatorClass()方法设置的key比较函数类,对所有数据进行排序。然后开始构造一个key对应的Value迭代器,这里就要用到分组,调用job.setGroupingComparatorClass()方法设置分组函数类,只要这个比较器比较的两个key相同,他们就属于同一个组,他们的value放在一个value迭代器中,而这个迭代器的key使用属于同一个的所有key的第一个key。最后进入Reducer的reduce方法,该方法的输入是所有的key和它的value迭代器。
 

二、二次排序样例

        假设要对如下文件进行排序,首先按照第一列字母进行排序,然后对每个字母所对应的第二列数字按大小进行排序。
a 5
a 3
b 2
c 9
b 10
a 1
c 8
b 6

排序结果如下:

a  1
a  3
a  5
b  2
b  6
b  10
c  8
c  9
 
 
(1)自定义key
        所有自定义的key应该实现接口WritableComparable,因为它是可序列化的且可比较。实现该接口必须要实现如下函数:
 
// 序列化,将 IntPair 序列化成二进制流
public void write(DataOutput dataOutput) throws IOException

// 反序列化,将读取的二进制流转换成 IntPair
public void readFields(DataInput dataInput) throws IOException

// key 的比较
public int compareTo(IntPair o)

// 默认的分区类 HashPartitioner, 使用此方法
public int hashCode()
 
(2)自定义分区
        自定义分区类FirstPartitioner,是key的第一次比较,完成对所有的key排序

  
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值