MapReduce Partitioner接口的设计与实现

Partitioner的作用是对Mapper产生的中间结果进行分片,以便将同一分组的数据交给同一个Reducer处理,它直接影响Reduce阶段的负载均衡。

MapReduce提供了两个Partitioner实现:HashPartitioner和TotalOrderPartioner。其中HashPartitioner是默认实现,它实现了一种基于哈希值的分片方法,代码如下:

public int getPartition(K2 key,V2 value,int numReduceTasks){

    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;

}

TotalOrderPartitioner提供了一种基于区间的分片方法,通常用在数据全排序中。

在MapReduce环境中,容易想到的全排序方案是归并排序,即在Map阶段,每个Map Task进行局部排序;在Reduce阶段,启动一个Reduce Task进行全局排序。由于作业只能有一个Reduce Task,因而Reduce阶段会成为作业的瓶颈。为了提高全局排序的性能和扩展性,MapReduce提供了TotalOrderPartitioner。它能够按照大小将数据分成若干个区间(分片),并保证后一个区间的所有数据均大于前一个区间数据,这使得全排序的步骤如下:

步骤1

数据采样。在Client端通过采样获取分片的分割点。Hadoop自带了几个采样算法,如IntercalSampler、RandomSampler、SplitSampler等。

步骤2

Map阶段。本阶段涉及两个组件,分别是Mapper和Partitioner。其中,Mapper可以采用IdentityMapper,直接将输入数据输出,但Partitioner必须选用TotalOrderPartitioner,它将步骤1中获取的分割点保存到trie树中以便快速定位任意一个记录所在的区间,这样,每个Map Task产生R个区间,且区间之间有序。

步骤3

Reduce阶段。每个Reducer对分配的区间数据进行局部排序,最终得到全排序数据。

从以上步骤可以看出,基于TotalOrderPartioner全排序的效率跟key分布规律和采样算法有直接关系;key值分布越均匀且采样越具有代表性,则Reduce Task负载越均衡,全排序效率越高。

TotalOrderPartioner有两个典型的应用实例:TeraSort和HBase批量数据导入。

posted @ 2020-10-13 11:25  飞舞的小蛇  阅读(191)  评论(0)    收藏  举报