Hadoop中的全排序和二次排序

1、MapReduce的全排序

(1)使用一个reduce进行排序。

  MapReduce默认保证同一个分区内的Key是有序的,但是不保证全局有序。如果我们将所有的数据全部发送到一个Reduce,就可以实现结果全局有序。所有的数据都发送到一个Reduce进行排序,这样不能充分利用集群的计算资源,而且在数据量很大的情况下,很有可能会出现OOM问题。

(2)自定义分区函数实现全局有序:

  MapReduce默认的分区函数是HashPartitioner,其实现的原理是计算map输出key的 hashCode ,然后对Reduce个数 求余,余数相同的 key 都会发送到同一个Reduce。若能够自定义分区函数。如下

  所有 Key < 10000 的数据都发送到Reduce 0;所有 10000 < Key < 20000 的数据都发送到Reduce 1;其余的Key都发送到Reduce 2;

  实现了Reduce 0的数据一定全部小于Reduce 1,且Reduce 1的数据全部小于Reduce 2,再加上同一个Reduce里面的数据局部有序,这样就实现了数据的全局有序。 缺点:无法确定各个Reduce的分界点,也就无法使得分散到每个Reduce的数据量均衡。

(3)使用TotalOrderPartitioner进行全排序

  Hadoop 内置还有个名为 TotalOrderPartitioner 的分区实现类,它解决全排序的问题。其主要根据Key的分界点将不同的Key发送到相应的分区。但数据量较大时不可能对所有的数据进行分析然后选出 N-1 (N代表Reduce的个数)个分割点,最适合的方式是对数据进行抽样,然后对抽样的数据进行分析并选出合适的分割点。

  1)Hadoop内置的数据抽象方法

   a、SplitSampler:从s个split中选取前n条记录取样

   b、RandomSampler:随机取样

   c、IntervalSampler:从s个split里面按照一定间隔取样,通常适用于有序数据

  这三个抽样都实现了 getSample(InputFormat inf, Job job)方法,返回抽样到的Key数组,除了 IntervalSampler 类返回的抽样Key是有序的,其他都无序。获取到采样好的Key数组之后,需要对其进行排序,然后选择好N-1 (N代表Reduce的个数)个分割点,最后将这些Key分割点存储到指定的HDFS文件中,存储的文件格式是SequenceFile

(2)MapReduce的辅助排序

  1)核心思想:

   a、分区,假设有海量的数据,为了增加并行度,按照hash算法将所有数据分区后,确保同一年的数据进入到同一个分区,也就是同一个reduce里。

   b、键比较器,将数据拆分后,将需要排序的字段组成一个组合键(本质就是一个对象),因为采用组合键的key,需要一个键排序比较器来对key排序,通过年份升序,数据降序的算法编写核心比较方法。 那么mapper就会安装key比较器将自己所负责的所有数据排序。Java中实现类排序的接口时comparable,而Hadoop中实现类排序的接口是WritableComparable,实现其中的compareTo方法。

posted on 2019-06-15 11:51  hdc520  阅读(483)  评论(0)    收藏  举报

导航