1 二次排序
1.1 思路
所谓二次排序,对第1个字段相同的数据,使用第2个字段进行排序。
举个例子,电商平台记录了每一用户的每一笔订单的订单金额,现在要求属于同一个用户的所有订单金额作排序,并且输出的用户名也要排序。
账户 | 订单金额 |
---|---|
hadoop@apache | 200 |
hive@apache | 550 |
yarn@apache | 580 |
hive@apache | 159 |
hadoop@apache | 300 |
hive@apache | 258 |
hadoop@apache | 300 |
yarn@apache | 100 |
hadoop@apache | 150 |
yarn@apache | 560 |
yarn@apache | 260 |
二次排序后的结果
账户 | 订单金额 |
---|---|
hadoop@apache | 150 |
hadoop@apache | 200 |
hadoop@apache | 300 |
hadoop@apache | 300 |
hive@apache | 159 |
hive@apache | 258 |
hive@apache | 550 |
yarn@apache | 100 |
yarn@apache | 260 |
yarn@apache | 560 |
yarn@apache | 580 |
实现的思路是使用自定义key,key中实现按用户名和订单金额2个字段的排序,自定义分区和分组类,按用户名进行分区和分组。自定义排序的比较器,分别用于在map端和reduce的合并排序。
因为hadoop默认使用的字符串序列化java.io.DataOutputStream.writeUTF(), 使用了”变种的UTF编码”,序列化后的字节流不能在RawComparator使用。
在实现中,用一种变通的方法,直接使用“账户”字段的字节流,并且把字节流长度也一并序列化。RawComparator得到的字节流就是我们写进去的字节流。当然,在进行反序列化时,需要根据这个长度来读出“账户”字段。
1.2 实现
程序代码
public class SecondarySortMapReduce extends Configured implements Tool {
/**
* 消费