zoukankan      html  css  js  c++  java
  • 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。

  • 相关阅读:
    ZJOI 2019 划水记
    【博弈论】浅谈泛Nim游戏
    HZNU ACM一日游 2019.3.17 【2,4,6-三硝基甲苯(TNT)】
    BZOJ 1008 越狱 组合数学
    BZOJ 1036 树的统计Count 树链剖分模板题
    BZOJ 1012 最大数maxnumber 线段树
    BZOJ 1001 狼抓兔子 平面图的最小割
    SGU---107 水题
    欧拉回路模板
    hdu-3397 Sequence operation 线段树多种标记
  • 原文地址:https://www.cnblogs.com/1iHu4D0n9/p/8372753.html
Copyright © 2011-2022 走看看