Hadoop实现二次排序
一、二次排序简介
MapReduce框架在记录到达Reducer之前按键对进行排序,但是键对所对应的值没有被排序。甚至在不同的执行轮次中,这些值也不固定,因为它们来自于不同的map任务,且这些任务在不同的轮次中完成时间各不相同。换言之,MapReduce框架默认只对Key升序排序,不对Value排序,因此,就需要用到二次排序(又称为辅助排序)。比如需要这样的需求:现在有海量的 年份-温度 数据,经过排序后,想要得到这样的结果:年份升序排序,统一年份的温度降序排序。因而,需要对Key进行组合,自定义一个Key类型,将年份与温度组合在一起,实现既对Key排序,又对Value排序。
二、二次排序的原理
二次排序的原理如下图:
首先我们编写一个组合Key,将年份与温度组合为一个Key,值为Null,并且给出序列化与反序列化,排序等方法。从文本读取数据进入Map,将数据封装进自定义类中,自定义一个分区类,规定相同年份的Key进入同一个分区,然后combiner(可选)。Shuffle后进入到Reduce,相同年份的Key会进入相同的reducer,此时会依照我们编写的规则进行排序(年份升序,同一年的温度降序),从而需要我们定义一个排序对比器类,排完序后,满足同一组内的Key要进入同一个reducer函数进行聚合,因此需要我们编写分组对比器类,最后输出结果。
三、二次排序的实现
1.构建Java工程,添加Maven支持
本次实操采用的开发工具是IDEA2018,Hadoop版本是2.6.0-cdh5.7.0
完整Maven依赖:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<hadoop.version>2.6.0-cdh5.7.0</hadoop.version>
</properties>
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${
hadoop.version}</version>
</dependency>
</dependencies>
1.编写ComboKey类
/**
* 自定义key,实现WritableComparable接口
* 可串行化,自定义比较规则
*/
public class ComboKey implements WritableComparable<ComboKey> {
private int year; //年份
private int temp; //温度
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getTemp() {