hadoop的分区、分组与排序的理解

  首先需要明确的是,hadoop里的key一定要是可排序的,要么key自身实现了WritableComparator接口,要么有一个排序类可以对key进行排序。如果key本身不实现WritableComparator接口,而是由另外的一个工具类(实现RawComparator接口)来提供排序的话,需要单独设置key的排序类:

job.setOutputKeyComparatorClass(XXX.class);


在map输出的时候,会进行分片,在片内再对key进行排序。分片的作用是确定分发到哪个reduce;排序的原因是为后一阶段的reduce的排序做好基础,以便归并排序的时候更快。

reduce端搜集到众多map节点的输出后,也会按照key进行排序。排序要么是根据提供的单独排序类,如果没有,则是要求key一定要实现WritableComparator接口,否则cast的时候会报异常。

我们写的reduce方法里,接收的参数中,value是一个迭代的值,框架把key ”相同“的k-v的v值,放在一个迭代器里。reduce方法的key参数,取得是第一个k-v的k值。key是否相同是由业务决定的,不像数字1=1这样的绝对比较。这个过程叫做分组。相同组内的k-v,由同一次的reduce方法处理。分组需要一个分组方法,来确定哪些k-v是一组的。分组方法比较的还是key的值。如果提供了单独的分组器,就使用单独的分组器来进行分组,否则默认行为就是进行key 的比较(key本身的compare方法或者单独的比较方法),比较一致的,就放在一个组里。有时候,key虽然不同,但是又希望它们在一个组里,此时,就需要单独提供一个分组方法了。由job.setOutputValueGroupingComparator()方法设定。在这种key不相同,却在同一个组的时候,传递给我们写的reduce方法的key由于是取第一个k-v的k值,那么k的排序就显得很重要了。通过排序,将需要的k-v排在第一位,可以借此达到某些目的。如进行联查的时候。

例如:有两个文件,一个是city.txt,一个是person.txt,city里记录的是城市编号以及城市名称,以逗号分隔,person文件里记录的是城市编号与姓名,希望最终得到姓名-城市名称的结果。

这个方法有很多解,这里就举一个:想办法将同一城市的人包括该城市的名称放在一个组里,同时将城市名称放在第一位,那么在reduce端,取到第一个value就是城市的名称了,其余的就是人的姓名。

city.txt

1,gz

2,zh

3,dg


person.txt

1,lili

2,huangq

2,chaojie

3,pengming

3,duw


定义一个结构作为key:

CityPerson implements WritableComparator{

int cityId;

int flag;

}

约定city的flag=1,person的flag=0.

排序方法是flag=1的排在前面。

@Override 
 public int compareTo(CityPerson o) { 
 
 if(cityId==o.cityId){ 

          //大的在前 

              if(flag>o.flag){ return -1; }

             else   if(flag<o.flag){ return 1; } 

             return 0; 

         }
 
 return (cityId>o.cityId)?1:-1;

}


经过reduce端的最后排序,所以的k-v都排好了,而且,相同cityid的,flag=1的会排在前面。

由于此CityPerson的比较方法,已经不能用来分组了(相同cityid,不同flag的比较不为0,就不会放在一个组,而要求是cityid相同的需要放在一个组里),所以,需要单独提供一个分组器,

public class GroupComparator implements RawComparator<CityPerson>{


@Override
public int compare(CityPerson o1, CityPerson o2) {
if(o1.cityId==o2.cityId){
return 0;
}
return (o1.cityId>o2.cityId)?1:-1;
}


@Override
public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3,
int arg4, int arg5) {
return 0;
}

}


只比较cityid。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值