MapReduce程序开发中的Partitioner

2016年4月4日18:08:35

                                                                             MapReduce程序开发中的Partitioner

                                                                                         作者:数据分析玩家

  在MapReduce程序的执行过程中,也就是在Mapper阶段执行的第四步:将会对输出的键值对<k2,v2>进行分区,在编写MapReduce程序的驱动中,我们常常会写到下面两行代码:

                       job.setNumReduceTasks(1);
                       job.setPartitionerClass(HashPartitioner.class);

当然,如果不写的话也是可以的,因为MapReduce是默认的:默认分区的类是HashPartitioner,默认Reducer任务的数量是1个,而我们在学习MapReduce的过程中,总是说Reducer任务的数量和分区的数量是相等的,那么我们可以猜想HashPartitioner这个默认的类就是指定分为一个区,那到底是不是呢?现在我们查看源码:    

                     

       通过源码我们可以知道:HashPartitioner类继承了Partitioner类,并重写了里面的 getPartition()方法,而在方法体中,不难发现返回值总是1,这也恰恰证明了在MapReduce中分区的数量和Reducer任务的数量是相等的。

接下来我们要讲的是分区的优点:

1>根据业务需要,通过分区可以产生多个输出文件.

如在统计手机流量的业务当中,手机号的信息分到一个区,非手机号的信息分到另外一个区.

2>多个分区意味着有多个Reducer任务,因为分区的数量与Reducer的数量是相等的,而Reducer任务是在TaskTracker节点上运行的,因此多个Reducer任务意味着有多个TaskTracker节点在执行任务,而TaskTracker又是独立的物理机器,因此多个分区在一定程度上可以提高job的运行效率.

但是Reducer任务越多,意味着分区数量越多,意味着数据{<k2,v2>}处理的越分散,Mapper任务要把数据送到Reducer任务的话,需要走网络,这样Reducer任务越多,浪费的时间就越多.

因此到底每一个Mapper任务输出的数据分散到几个区,根据的是现场集群的情况、业务的要求情况。

接下来我们要讨论的是如何自定义分区,其实自定义分区是很简单的,只需要做两步:

1>编写自定义的MyCombiner

如在手机业务的流量统计当中,设置手机号的数据输出到一个区,非手机号的输出到一个区,自定义类如下:

         

2>在驱动中导入自定义的MyCombiner类,并设置Reducer任务的数量与分区的数量想等。

         job.setNumReduceTasks(2);//指定Reducer的任务数量为2
         job.setPartitionerClass(MyPartitioner.class);//指定自定义的分区类MyReducer

注意:若在程序中自定义了分区,那么程序的运行只能在linux命令行下执行:即jar包的方式

现在我们将执行的结果列出:

MapReduce程序开发中的Partitioner_第1张图片

通过结果我们可以发现:输出的数据被分到了两个区:00000区与00001区,方便我们的观察。

                                                                 

                                                                        2016年4月4日20:36:24


  
       

你可能感兴趣的:(MapReduce运行原理)