MapTask类

在MapTask类中找到run函数

  1. if(useNewApi){
  2.       runNewMapper(job, splitMetaInfo, umbilical, reporter);
  3.     }
再找到runNewMapper
  1. @SuppressWarnings("unchecked")
  2.   private<INKEY,INVALUE,OUTKEY,OUTVALUE>
  3.   void runNewMapper(final JobConf job,
  4.                     final TaskSplitIndex splitIndex,
  5.                     final TaskUmbilicalProtocol umbilical,
  6.                     TaskReporter reporter
  7.                     ) throws IOException,ClassNotFoundException,
  8.                              InterruptedException{
  9.     // make a task context so we can get the classes
  10.     org.apache.hadoop.mapreduce.TaskAttemptContext taskContext =
  11.       new org.apache.hadoop.mapreduce.task.TaskAttemptContextImpl(job,
  12.                                                                   getTaskID(),
  13.                                                                   reporter);
  14.     // make a mapper
  15.     org.apache.hadoop.mapreduce.Mapper<INKEY,INVALUE,OUTKEY,OUTVALUE> mapper =
  16.       (org.apache.hadoop.mapreduce.Mapper<INKEY,INVALUE,OUTKEY,OUTVALUE>)
  17.         ReflectionUtils.newInstance(taskContext.getMapperClass(), job);
  18.     // make the input format
  19.     org.apache.hadoop.mapreduce.InputFormat<INKEY,INVALUE> inputFormat =
  20.       (org.apache.hadoop.mapreduce.InputFormat<INKEY,INVALUE>)
  21.         ReflectionUtils.newInstance(taskContext.getInputFormatClass(), job);
  22.     // rebuild the input split
  23.     org.apache.hadoop.mapreduce.InputSplit split = null;
  24.     split = getSplitDetails(newPath(splitIndex.getSplitLocation()),
  25.         splitIndex.getStartOffset());
  26.     LOG.info("Processing split: "+ split);
  27.  
  28.     org.apache.hadoop.mapreduce.RecordReader<INKEY,INVALUE> input =
  29.       newNewTrackingRecordReader<INKEY,INVALUE>
  30.         (split, inputFormat, reporter, taskContext);
  31.  
  32.     job.setBoolean(JobContext.SKIP_RECORDS, isSkipping());
  33.     org.apache.hadoop.mapreduce.RecordWriter output = null;
  34.  
  35.     // get an output object
  36.     if(job.getNumReduceTasks()==0){
  37.       output =  如果jreduce个数等于0.则执行该方法
  38.         newNewDirectOutputCollector(taskContext, job, umbilical, reporter);
  39.     }else{
  40.        如果reduce个数大于0.则执行该方法
  41.       output =newNewOutputCollector(taskContext, job, umbilical, reporter);
  42.     }
  43.  
  44.     org.apache.hadoop.mapreduce.MapContext<INKEY, INVALUE, OUTKEY, OUTVALUE>
  45.     mapContext =
  46.       newMapContextImpl<INKEY, INVALUE, OUTKEY, OUTVALUE>(job, getTaskID(),
  47.           input, output,
  48.           committer,
  49.           reporter, split);
  50.  
  51.     org.apache.hadoop.mapreduce.Mapper<INKEY,INVALUE,OUTKEY,OUTVALUE>.Context
  52.         mapperContext =
  53.           newWrappedMapper<INKEY, INVALUE, OUTKEY, OUTVALUE>().getMapContext(
  54.               mapContext);
  55.  
  56.     try{
  57.       input.initialize(split, mapperContext);
  58.       mapper.run(mapperContext);
  59.       mapPhase.complete();
  60.       setPhase(TaskStatus.Phase.SORT);
  61.       statusUpdate(umbilical);
  62.       input.close();
  63.       input = null;
  64.       output.close(mapperContext);
  65.       output = null;
  66.     } finally {
  67.       closeQuietly(input);
  68.       closeQuietly(output, mapperContext);
  69.     }
  70.   }
我们知道,分区是在map函数输出的时候做的 ,所以这里是get output object
  1. // get an output object
  2.     if(job.getNumReduceTasks()==0){
  3.  
  4.       output =  如果jreduce个数等于0.则执行该方法
  5.         newNewDirectOutputCollector(taskContext, job, umbilical, reporter);
  6.     }else{
  7.        如果reduce个数大于0.则执行该方法
  8.       output =newNewOutputCollector(taskContext, job, umbilical, reporter);
  9.     }
如果没有reduce任务,则new NewDirectOutputCollector()
(Collection过程我还没探索过呢)
如果有NewOutputCollector任务,则运行new NewOutputCollector()
 
内部类NewOutputCollector
在内部类NewOutputCollector中找到该方法(构造方法)
  1. NewOutputCollector(org.apache.hadoop.mapreduce.JobContext jobContext,
  2.                        JobConf job,
  3.                        TaskUmbilicalProtocol umbilical,
  4.                        TaskReporter reporter
  5.                        ) throws IOException,ClassNotFoundException{
  6.       collector = createSortingCollector(job, reporter);
  7.  
  8.       partitions = jobContext.getNumReduceTasks();
  9.  
  10.       if(partitions >1){
  11.         partitioner =(org.apache.hadoop.mapreduce.Partitioner<K,V>)
  12.           ReflectionUtils.newInstance(jobContext.getPartitionerClass(), job);
  13.       }else{
  14.         partitioner =new org.apache.hadoop.mapreduce.Partitioner<K,V>(){
  15.           @Override
  16.           publicint getPartition(K key, V value,int numPartitions){
  17.             return partitions -1;
  18.           }
  19.         };
  20.       }
  21.     }
通过partitions = jobContext.getNumReduceTasks();语句获取到Reduce任务个数
如果Reduce任务数小于等于1,则新建一个Partitioner对象的同时并复写getPartition方法,这个复写的方法直接统一返回-1,就都在一个分区了。
如果Reduce任务数大于 ,则通过反射创建jobContext.getPartitionerClass()获取到的对象
于是查看:
jobContext接口
jobContext接口中的
  1. /**
  2.    * Get the {@link Partitioner} class for the job.
  3.    *
  4.    * @return the {@link Partitioner} class for the job.
  5.    */
  6.   publicClass<? extends Partitioner<?,?>> getPartitionerClass()
  7.      throws ClassNotFoundException;
我们还是看其实现类jobContextImpl吧
jobContextImpl类
注意是在mapreduce包下啊,不是mapred包下
  1. /**
  2.    * Get the {@link Partitioner} class for the job.
  3.    *
  4.    * @return the {@link Partitioner} class for the job.
  5.    */
  6.   @SuppressWarnings("unchecked")
  7.   publicClass<? extends Partitioner<?,?>> getPartitionerClass()
  8.      throws ClassNotFoundException{
  9.     return(Class<? extends Partitioner<?,?>>)
  10.       conf.getClass(PARTITIONER_CLASS_ATTR,HashPartitioner.class);
  11.   }
conf.getClass(PARTITIONER_CLASS_ATTR, HashPartitioner.class);
的意思是,从PARTITIONER_CLASS_ATTR属性中取出值,作为类返回,如果不存在,则使用和默认值HashPartitioner.class
也就是说,当Reduce个数大于1的时候,其默认调用的是HashPartitioner.class
  1. publicclassHashPartitioner<K, V>extendsPartitioner<K, V>{
  2. /** Use {@link Object#hashCode()} to partition. */
  3. publicint getPartition(K key, V value,
  4. int numReduceTasks){
  5. return(key.hashCode()&Integer.MAX_VALUE)% numReduceTasks;
  6. }
  7. }
发现HashPartitioner调用的是getPartition方法,最终使用的是key对象中的hashcode方法
而我们使用eclipse(Alt+Shift+ S  按下H)复写的hashcode是将两个属性(账户和金额都考虑进去了)
嗯,果然自己修改自定义key类中的hashcode,测试了一下是可以的,只要hashcode是只根据我们的账户account进行生产
  1. @Override
  2.         publicint hashCode(){
  3.             final int prime =31;
  4.             int result =1;
  5.             result = prime * result +((account == null)?0: account.hashCode());
  6.      //     result = prime * result + ((amount == null) ? 0 : amount.hashCode());
  7.             return result;
  8.         }
 
另一种更主流的方式:
自定义的Partition类为什么要是Group的内部类呢?自己改为外部类自己测试下,发现完全可以
具体的形式
  1. publicstaticclassKeyPartitioner extends  Partitioner<SelfKey,DoubleWritable>{
  2.  
  3.             @Override
  4.             publicint getPartition(SelfKey key,DoubleWritable value,int numPartitions){
  5.                 /**
  6.                  * 如何保证数据整体输出上的有序,需要我们自定义业务逻辑
  7.                  * 必须提示前知道num reduce task 个数?
  8.                  * \w  单词字符[a-zA-Z_0-9]
  9.                  *  
  10.                  */
  11.                 String account =key.getAccount();
  12.                 //0xxaaabbb 0-9 
  13.                 //[0-2][3-6][7-9]
  14.                 if(account.matches("\\w*[0-2]")){
  15.                     return0;
  16.                 }elseif(account.matches("\\w*[3-6]")){
  17.                     return1;
  18.                 }elseif(account.matches("\\w*[7-9]")){
  19.                     return2;
  20.                 }
  21.                 return0;
  22.  
  23.             }
  24.         }
这是为了保证S1和S2都在分区1,而不会出现S1中的其中几个在分区1 ,另外几个在分区2
因为我们此时的键——是账户+金额,所以可能明明都是账户S1的分区却不一样,最后导致排序混乱?
 
 
 

关于MapReduce中自定义分区类(四)的更多相关文章

  1. 关于MapReduce中自定义分组类(三)

    Job类  /**    * Define the comparator that controls which keys are grouped together    * for a single ...

  2. 关于MapReduce中自定义Combine类(一)

    MRJobConfig      public static fina COMBINE_CLASS_ATTR      属性COMBINE_CLASS_ATTR = "mapreduce.j ...

  3. 在hadoop作业中自定义分区和归约

    当遇到有特殊的业务需求时,需要对hadoop的作业进行分区处理 那么我们可以通过自定义的分区类来实现 还是通过单词计数的例子,JMapper和JReducer的代码不变,只是在JSubmit中改变了设 ...

  4. 关于MapReduce中自定义带比较key类、比较器类(二)——初学者从源码查看其原理

    Job类 /**   * Define the comparator that controls    * how the keys are sorted before they   * are pa ...

  5. MapReduce之自定义分区器Partitioner

    @ 目录 问题引出 默认Partitioner分区 自定义Partitioner步骤 Partition分区案例实操 分区总结 问题引出 要求将统计结果按照条件输出到不同文件中(分区). 比如:将统计 ...

  6. python3.4中自定义数组类(即重写数组类)

    '''自定义数组类,实现数组中数字之间的四则运算,内积运算,大小比较,数组元素访问修改及成员测试等功能''' class MyArray: '''保证输入值为数字元素(整型,浮点型,复数)''' de ...

  7. flask中自定义日志类

    一:项目架构 二:自定义日志类 1. 建立log.conf的配置文件 log.conf [log] LOG_PATH = /log/ LOG_NAME = info.log 2. 定义日志类 LogC ...

  8. 读取SequenceFile中自定义Writable类型值

    1)hadoop允许程序员创建自定义的数据类型,如果是key则必须要继承WritableComparable,因为key要参与排序,而value只需要继承Writable就可以了.以下定义一个Doub ...

  9. Java中自定义注解类,并加以运用

    在Java框架中,经常会使用注解,而且还可以省很多事,来了解下自定义注解. 注解是一种能被添加到java代码中的元数据,类.方法.变量.参数和包都可以用注解来修饰.注解对于它所修饰的代码并没有直接的影 ...

随机推荐

  1. screen:多重视窗管理程序

    screen:多重视窗管理程序 screen [-S SCREEN_NAME]: 创建窗口,可指定窗口名称,如果不指定,则是ID.$HOSTNAME screen -ls: 列出所有的screen窗口 ...

  2. 关于 AVI 的一些代码

    #ifndef __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__ #define __HSS_AUTO_REVISE_AVI_FRAMERATE_HSS__ /******* ...

  3. apache 开机自启动脚本设置

    默认我们源码编译安装apache,是不能使用service这个命令来启动的,通常我们启动的命令是: [root@localhost httpd-2.2.16]# /usr/local/apache2/ ...

  4. Swift和Objective-C混编注意事项

    前言 Swift已推出数年,与Objective-C相比Swift的语言机制及使用简易程度上更接地气,大大降低了iOS入门门槛.当然这对新入行的童鞋没来讲,的确算是福音,但对于整个iOS编程从业者来讲 ...

  5. 个人CTF资源聚合

    i春秋 幻泉 CTF入门课程笔记 视频地址 能力 思维能力 快速学习能力 技术能力 基础 编程基础 (c语言 汇编语言 脚本语言) 数学基础 (算法 密码学) 脑洞 (天马行空的想象推理) 体力耐力( ...

  6. WinCE项目应用之车载导航

    WinCE车载导航系统是我过去几年投入精力比较多的一个项目.我的主要工作内容是BSP的移植.硬件模块的调试和WinCE系统的深度定制.如TDA7415驱动.TDA7415均衡器.慧翰车载蓝牙模块.华为 ...

  7. webpack入门——webpack的安装与使用

    一.简介 1.什么是webpack webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都作为模块来使用和处理. ...

  8. [LeetCode] Ones and Zeroes 一和零

    In the computer world, use restricted resource you have to generate maximum benefit is what we alway ...

  9. [LeetCode] Fizz Buzz 嘶嘶嗡嗡

    Write a program that outputs the string representation of numbers from 1 to n. But for multiples of ...

  10. [LeetCode] Number of 1 Bits 位1的个数

    Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also know ...