Hadoop二次排序总结
最近学习hadoop二次排序,在此对自己总结的内容做些记录,首先是Map端:
1.自定义数据类型CombinationKey -> 重组后的数据类型(将原始数据Key,Value组合)
实现WritableComparable接口,其中writableComparable继承Writable、Comparable接口,所以重整后的Key需要实现:
a.Writable接口(输入输出)
public interface Writable { void write(DataOutput out) throws IOException; void readFields(DataInput in) throws IOException; }
在IntWritable中的实现如下:
@Override public void readFields(DataInput in) throws IOException { value = in.readInt(); } @Override public void write(DataOutput out) throws IOException { out.writeInt(value); }
b.Comparable接口
@Override public boolean equals(Object o) { if (!(o instanceof IntWritable)) return false; IntWritable other = (IntWritable)o; return this.value == other.value; } @Override public int hashCode() { return value; } /** Compares two IntWritables. */ @Override public int compareTo(IntWritable o) { int thisValue = this.value; int thatValue = o.value; return (thisValue<thatValue ? -1 : (thisValue==thatValue ? 0 : 1)); }
2.自定义分区器Partition
如果不对新组合Key定义分区器,hadoop分区时将默认比较整个Key值,而这里我们只需要其依据原始数据的Key值对数据进行分区。
因此新的分区器只要比较新Key的首列数据,继承Partitioner类,重写getPartition方法
public class DefinedPartition extends Partitioner<CombinationKey, IntWritable>{ /** * 数据输入来源:map输出 我们这里根据组合键的第一个值作为分区 * 如果不自定义分区的话,MapReduce会根据默认的Hash分区方法 * 将整个组合键相等的分到一个分区中,这样的话显然不是我们要的效果 * @param key map输出键值 * @param value map输出value值 * @param numPartitions 分区总数,即reduce task个数 */ public int getPartition(CombinationKey key, IntWritable value, int numPartitions) { return (key.getFirstKey().hashCode() & Integer.MAX_VALUE) % numPartitions; } }
3.自定义排序器Comparator
分区完成后,需要对组合数据分别排序,排序原则是先根据组合首列值升序排列,然后再根据第二列升序排列
public int compare(WritableComparable a, WritableComparable b) { CombinationKey c1 = (CombinationKey) a; CombinationKey c2 = (CombinationKey) b; int minus = c1.getFirstKey().compareTo(c2.getFirstKey()); if (minus != 0){ return minus; } else { return c1.getSecondKey().get() -c2.getSecondKey().get(); } }
至此Map端暂告一段落,下面是reducer端:
4.自定义分组器GroupSort
依据组合Key的首列分组,每处理一次调用一次reducer来对分组进行输出
@Override public int compare(WritableComparable a, WritableComparable b) { CombinationKey combinationKey1 = (CombinationKey) a; CombinationKey combinationKey2 = (CombinationKey) b; //自定义按原始数据中第一个key分组 return combinationKey1.getFirstKey().compareTo(combinationKey2.getFirstKey()); }
5.主体程序部分
a. Mapper
1)过滤非法数据
2)设置联合Key值
3)输出(联合Key值,value值)
b.Reducer
输出(联合Key值首列值,value值)
c.run
1)获取配置信息
2)创建Job任务
3)设置输入输出路径,因为MapReduce输出路径已经存在将不能正常输出的设定,如果是固定输出路径,此处可增加输出路径文件系统是否存在的判断
4)设置Map类和map方法的输出Key,value类型
5)设置分区器 job.setPartitionerClass
6)设置分组策略job.setGroupingComparatorClass
7)设置比较策略job.setSortComparatorClass
8)设置Reducer类和reduce方法的输出类型
9)提交作业job.waitForCompletion(true)
d.main方法
1)创建配置
2)获取或指定输入输出路径(此处可以run方法中直接指定)
3)调用ToolRunner.run方法
4)退出 System.exit
学习中https://blog.csdn.net/lzm1340458776/article/details/42875751帮助很大,本文多处涉及到,在此特别感谢,受益匪浅,谢谢。

浙公网安备 33010602011771号