reduce的数目到底和哪些因素有关

1、我们知道map的数量和文件数、文件大小、块大小、以及split大小有关,而reduce的数量跟哪些因素有关呢?

设置mapred.tasktracker.reduce.tasks.maximum的大小可以决定单个tasktracker一次性启动reduce的数目,但是不能决定总的reduce数目。

conf.setNumReduceTasks(4);JobConf对象的这个方法可以用来设定总的reduce的数目,看下Job Counters的统计:

  1. Job Counters
  2. Data-local map tasks=2
  3. Total time spent by all maps waiting after reserving slots (ms)=0
  4. Total time spent by all reduces waiting after reserving slots (ms)=0
  5. SLOTS_MILLIS_MAPS=10695
  6. SLOTS_MILLIS_REDUCES=29502
  7. Launched map tasks=2
  8. Launched reduce tasks=4

确实启动了4个reduce:看下输出:

  1. diegoball@diegoball:~/IdeaProjects/test/build/classes$ hadoop fs -ls  /user/diegoball/join_ou1123
  2. 11/03/25 15:28:45 INFO security.Groups: Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000
  3. 11/03/25 15:28:45 WARN conf.Configuration: mapred.task.id is deprecated. Instead, use mapreduce.task.attempt.id
  4. Found 5 items
  5. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:28 /user/diegoball/join_ou1123/_SUCCESS
  6. -rw-r--r--   1 diegoball supergroup        124 2011-03-25 15:27 /user/diegoball/join_ou1123/part-00000
  7. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:27 /user/diegoball/join_ou1123/part-00001
  8. -rw-r--r--   1 diegoball supergroup        214 2011-03-25 15:28 /user/diegoball/join_ou1123/part-00002
  9. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:28 /user/diegoball/join_ou1123/part-00003

只有2个reduce在干活。为什么呢?

shuffle的过程,需要根据key的值决定将这条<K,V> (map的输出),送到哪一个reduce中去。送到哪一个reduce中去靠调用默认的org.apache.hadoop.mapred.lib.HashPartitioner的getPartition()方法来实现。
HashPartitioner类:

  1. package org.apache.hadoop.mapred.lib;
  2. import org.apache.hadoop.classification.InterfaceAudience;
  3. import org.apache.hadoop.classification.InterfaceStability;
  4. import org.apache.hadoop.mapred.Partitioner;
  5. import org.apache.hadoop.mapred.JobConf;
  6. /** Partition keys by their {@link Object#hashCode()}.
  7. */
  8. @InterfaceAudience.Public
  9. @InterfaceStability.Stable
  10. public class HashPartitioner<K2, V2> implements Partitioner<K2, V2> {
  11. public void configure(JobConf job) {}
  12. /** Use {@link Object#hashCode()} to partition. */
  13. public int getPartition(K2 key, V2 value,
  14. int numReduceTasks) {
  15. return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  16. }
  17. }

numReduceTasks的值在JobConf中可以设置。默认的是1:显然太小。
   这也是为什么默认的设置中总启动一个reduce的原因。

返回与运算的结果和numReduceTasks求余。

Mapreduce根据这个返回结果决定将这条<K,V>,送到哪一个reduce中去。

key传入的是LongWritable类型,看下这个LongWritable类的hashcode()方法:

  1. public int hashCode() {
  2. return (int)value;
  3. }

简简单单的返回了原值的整型值。

因为getPartition(K2 key, V2 value,int numReduceTask)返回的结果只有2个不同的值,所以最终只有2个reduce在干活。

HashPartitioner是默认的partition类,我们也可以自定义partition类 :

  1. package com.alipay.dw.test;
  2. import org.apache.hadoop.io.IntWritable;
  3. import org.apache.hadoop.mapred.JobConf;
  4. import org.apache.hadoop.mapred.Partitioner;
  5. /**
  6. * Created by IntelliJ IDEA.
  7. * User: diegoball
  8. * Date: 11-3-10
  9. * Time: 下午5:26
  10. * To change this template use File | Settings | File Templates.
  11. */
  12. public class MyPartitioner implements Partitioner<IntWritable, IntWritable> {
  13. public int getPartition(IntWritable key, IntWritable value, int numPartitions) {
  14. /* Pretty ugly hard coded partitioning function. Don't do that in practice, it is just for the sake of understanding. */
  15. int nbOccurences = key.get();
  16. if (nbOccurences > 20051210)
  17. return 0;
  18. else
  19. return 1;
  20. }
  21. public void configure(JobConf arg0) {
  22. }
  23. }

仅仅需要覆盖getPartition()方法就OK。通过:
conf.setPartitionerClass(MyPartitioner.class);
可以设置自定义的partition类。
同样由于之返回2个不同的值0,1,不管conf.setNumReduceTasks(4);设置多少个reduce,也同样只会有2个reduce在干活。

由于每个reduce的输出key都是经过排序的,上述自定义的Partitioner还可以达到排序结果集的目的:

  1. 11/03/25 15:24:49 WARN conf.Configuration: mapred.task.id is deprecated. Instead, use mapreduce.task.attempt.id
  2. Found 5 items
  3. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:23 /user/diegoball/opt.del/_SUCCESS
  4. -rw-r--r--   1 diegoball supergroup      24546 2011-03-25 15:23 /user/diegoball/opt.del/part-00000
  5. -rw-r--r--   1 diegoball supergroup      10241 2011-03-25 15:23 /user/diegoball/opt.del/part-00001
  6. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:23 /user/diegoball/opt.del/part-00002
  7. -rw-r--r--   1 diegoball supergroup          0 2011-03-25 15:23 /user/diegoball/opt.del/part-00003

part-00000和part-00001是这2个reduce的输出,由于使用了自定义的MyPartitioner,所有key小于20051210的的<K,V>都会放到第一个reduce中处理,key大于20051210就会被放到第二个reduce中处理。
每个reduce的输出key又是经过key排序的,所以最终的结果集降序排列。

但是如果使用上面自定义的partition类,又conf.setNumReduceTasks(1)的话,会怎样? 看下Job Counters:

  1. Job Counters
  2. Data-local map tasks=2
  3. Total time spent by all maps waiting after reserving slots (ms)=0
  4. Total time spent by all reduces waiting after reserving slots (ms)=0
  5. SLOTS_MILLIS_MAPS=16395
  6. SLOTS_MILLIS_REDUCES=3512
  7. Launched map tasks=2
  8. Launched reduce tasks=1

只启动了一个reduce。
  (1)、 当setNumReduceTasks( int a) a=1(即默认值),不管Partitioner返回不同值的个数b为多少,只启动1个reduce,这种情况下自定义的Partitioner类没有起到任何作用。
  (2)、 若a!=1:
   a、当setNumReduceTasks( int a)里 a设置小于Partitioner返回不同值的个数b的话:

  1. public int getPartition(IntWritable key, IntWritable value, int numPartitions) {
  2. /* Pretty ugly hard coded partitioning function. Don't do that in practice, it is just for the sake of understanding. */
  3. int nbOccurences = key.get();
  4. if (nbOccurences < 20051210)
  5. return 0;
  6. if (nbOccurences >= 20051210 && nbOccurences < 20061210)
  7. return 1;
  8. if (nbOccurences >= 20061210 && nbOccurences < 20081210)
  9. return 2;
  10. else
  11. return 3;
  12. }

同时设置setNumReduceTasks( 2)。

于是抛出异常:

  1. 11/03/25 17:03:41 INFO mapreduce.Job: Task Id : attempt_201103241018_0023_m_000000_1, Status : FAILED
  2. ava.io.IOException: Illegal partition for 20110116 (3)
  3. at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:900)
  4. at org.apache.hadoop.mapred.MapTask$OldOutputCollector.collect(MapTask.java:508)
  5. at com.alipay.dw.test.KpiMapper.map(Unknown Source)
  6. at com.alipay.dw.test.KpiMapper.map(Unknown Source)
  7. at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54)
  8. at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:397)
  9. at org.apache.hadoop.mapred.MapTask.run(MapTask.java:330)
  10. at org.apache.hadoop.mapred.Child$4.run(Child.java:217)
  11. at java.security.AccessController.doPrivileged(Native Method)
  12. at javax.security.auth.Subject.doAs(Subject.java:396)
  13. at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:742)
  14. at org.apache.hadoop.mapred.Child.main(Child.java:211)

某些key没有找到所对应的reduce去处。原因是只启动了a个reduce。
 
   b、当setNumReduceTasks( int a)里 a设置大于Partitioner返回不同值的个数b的话,同样会启动a个reduce,但是只有b个redurce上会得到数据。启动的其他的a-b个reduce浪费了。

c、理想状况是a=b,这样可以合理利用资源,负载更均衡。

reduce的数目到底和哪些因素有关的更多相关文章

  1. 019_Map Task数目的确定和Reduce Task数目的指定

    注意标题:Map Task数目的确定和Reduce Task数目的指定————自然得到结论,前者是后者决定的,后者是人为指定的.查看源码可以很容易看懂 1.MapReduce作业中Map Task数目 ...

  2. reduce个数问题

    reduce的数目到底和哪些因素有关 1.我们知道map的数量和文件数.文件大小.块大小.以及split大小有关,而reduce的数量跟哪些因素有关呢?  设置mapred.tasktracker.r ...

  3. reduce个数究竟和哪些因素有关

    reduce的数目究竟和哪些因素有关 1.我们知道map的数量和文件数.文件大小.块大小.以及split大小有关,而reduce的数量跟哪些因素有关呢?  设置mapred.tasktracker.r ...

  4. MapReduce剖析笔记之五:Map与Reduce任务分配过程

    在上一节分析了TaskTracker和JobTracker之间通过周期的心跳消息获取任务分配结果的过程.中间留了一个问题,就是任务到底是怎么分配的.任务的分配自然是由JobTracker做出来的,具体 ...

  5. Hadoop Map/Reduce教程

    原文地址:http://hadoop.apache.org/docs/r1.0.4/cn/mapred_tutorial.html 目的 先决条件 概述 输入与输出 例子:WordCount v1.0 ...

  6. 一步一步跟我学习hadoop(5)----hadoop Map/Reduce教程(2)

    Map/Reduce用户界面 本节为用户採用框架要面对的各个环节提供了具体的描写叙述,旨在与帮助用户对实现.配置和调优进行具体的设置.然而,开发时候还是要相应着API进行相关操作. 首先我们须要了解M ...

  7. MapReduce流程、如何统计任务数目以及Partitioner

    核心功能描述 应用程序通常会通过提供map和reduce来实现 Mapper和Reducer接口,它们组成作业的核心. Map是一类将输入记录集转换为中间格式记录集的独立任务. 这种转换的中间格式记录 ...

  8. 分布式基础学习(2)分布式计算系统(Map/Reduce)

    二. 分布式计算(Map/Reduce) 分 布式式计算,同样是一个宽泛的概念,在这里,它狭义的指代,按Google Map/Reduce框架所设计的分布式框架.在Hadoop中,分布式文件 系统,很 ...

  9. hadoop学习WordCount+Block+Split+Shuffle+Map+Reduce技术详解

    转自:http://blog.csdn.net/yczws1/article/details/21899007 纯干货:通过WourdCount程序示例:详细讲解MapReduce之Block+Spl ...

随机推荐

  1. 编码规范(二)之Code Templates的设置(转)

    http://swiftlet.net/archives/1199 编码规范(二)之Code Templates的设置(转) 文件(Files)注释标签:/** * @Title: ${file_na ...

  2. C++@冒号(:)和双冒号(::)的用法

    转自:http://blog.csdn.net/zimingjushi/article/details/6549390 1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) ty ...

  3. java多线程之:Java中的ReentrantLock和synchronized两种锁定机制的对比 (转载)

    原文:http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html 多线程和并发性并不是什么新内容,但是 Java 语言设计中的创新之 ...

  4. I/O Completions port

    http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-p ...

  5. docker安装错误

    转载:http://www.roddypy.com/index.php/2016/03/11/centos7-yum-%E5%AE%89%E8%A3%85docker%E6%8A%A5%E9%94%9 ...

  6. 怎么用ABBYY创建属于自己的PDF

    怎么创建一份属于自己的PDF文档呢?由于PDF格式文件具有跨平台.支持超长文件.安全可靠性高等诸多优势,在日常办公学习中应用越来越广泛.而随着技术的发展,各种办公软件也对PDF提供越来越多的支持,但P ...

  7. 全文检索引擎 Lucene.net

    全文搜索引擎是目前广泛应用的主流搜索引擎.它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行 ...

  8. noip2014普及组 比例简化

    题目描述 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果.例如,对某一观点表示支持的有1498 人,反对的有 902人,那么赞同与反对的比例可以简单的记为1498:902. 不过,如 ...

  9. iOS 下拉刷新和加载更多 (OC\Swift)

    Swift语言出来之后, 可能还没有第三方的下拉刷新和上提加载, 所以自己用UIRefreshControl控件和UITableView实例的tableFooterView(底部视图)属性结合起来写了 ...

  10. ant导入Zookeeper到Eclipse错误path contains invalid character

    首先在Zookeeper源码目录执行 ant eclipse 遇到错误 path contains invalid character 可以修改\zookeeper\build.xml 文件加入 &l ...