MR

分区:
   1.在MR中partitioner将Mapper产生的中间结果进行分区,然后将同一组数据提交给一个Reducer中处理
   2.partitioner默认调用的是Hashpartitioner,用它来把数据分组然后发送给不同的reducer
   3.计算公式:(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks
MR排关于分区和排序笔记
实现分区:
  1.继承Partitioner<key, value>,泛型为mapper输出的key和value,
   重写getPartition方法,返回的就是分区号
MR排关于分区和排序笔记
  2.在Driver类中指定partition类
  3.在Driver类中指定reducetask个数
MR排关于分区和排序笔记
总结
   1. 默认的reducetask数量为1,分区号从0递增
   2. 如果分区数量小于设置的reducetask数量(reducetask数量>1),那么会产生多余的空文件
   3. 如果分区数量大于设置的reducetask数量(reducetask数量>1),可能会有部分分区找不到reduce提交数据,出现异常
   4. 如果reducetask 数量不指定(默认为1),或者数量指定为1(job.setNumReduceTasks(1)),这两种情况都不会执行分区规则
排序:
  MR中分区后
  key默认的行为有两个:
    1.具有序列化反序列化
    2.排序
     默认是字典顺序,使用快排
  而value只需要有序列化和反序列化
MR排关于分区和排序笔记
对象实现自定义排序的两种方法:
1.实现WritableComparable<>接口,重写compareTo()方法MR排关于分区和排序笔记
2.自定义比较器继承WritableComparator类,父类构造方法需要增加比较的对象,重写compare()方法
并且需要在Driver中指定job.setSortComparatorClass(比较器类)
MR排关于分区和排序笔记
总结:
 1.如果对象实现自定义排序,必须实现WritableComparable<>接口
  2.如果自定义比较器并且指定比较器类但是没有重写compare方法,默认还是调用对象中的compareTo()方法
  3.如果自定义比较器并且指定比较器类和重写compare方法,就不会调用对象中的compareTo()方法了
对于总结的一些的解释
通过debug模式发现会优先调用 compare方法(在WritableComparator类中)MR排关于分区和排序笔记
实际上这里最后调用的compareTo方法是在实体类中实现WritableComparable<>接口,重写的compareTo()方法(如果实体类不继承WritableComparable<>接口,运行到这里就会出现类型转换异常)
但如果满足第三条就不会调用上图的compare方法,而是调用重写过的compare方法,这时,如果实体类(对象类)继承的不是WritableComparable<>,这里super调用父类方法会出错
MR排关于分区和排序笔记
我们进入到super中MR排关于分区和排序笔记
更改下实体类实现的接口就会发现类型不匹配MR排关于分区和排序笔记
所以:如果对象实现自定义排序,必须实现WritableComparable<>接口

相关文章: