Hadoop MapReduce之ReduceTask任务执行(五)

原创 2013年12月05日 15:30:43
  本节分析ReduceTask的最后一个阶段:reduce,经历了copy、sort后,reduce的输入数据就准备好了,reduce数据输入由Reducer.Context提供,该Context封装了sort阶段的迭代器,可以对内存和磁盘的KV进行迭代,这部分需要注意两个大的循环:1、对KEY的循环由Reducer类实现,具体参考run函数 2、在自定义的reduce函数中对VALUE的循环。在自定义的reduce函数中会处理迭代器中的数据,当迭代器中的数据没有的时候就意味着需要处理下一个KEY了,reduce函数的输出会直接输出目的地如HDFS中,具体位置是可以自定义的。下面我们先看Reducer中run函数是如何实现KEY循环的
  public void run(Context context) throws IOException, InterruptedException {
    setup(context);
    while (context.nextKey()) {//循环读取KEY
      reduce(context.getCurrentKey(), context.getValues(), context);//进入自定义的reduce函数
    }
    cleanup(context);
  }
nextKey函数的逻辑如下:
    /** Start processing next unique key. */
  public boolean nextKey() throws IOException,InterruptedException {
    while (hasMore && nextKeyIsSame) {//读取新KEY时nextKeyIsSame为假
      nextKeyValue();
    }
    if (hasMore) {
      if (inputKeyCounter != null) {
        inputKeyCounter.increment(1);
      }
      return nextKeyValue();//如果为新的KEY,则会预读一条KV
    } else {
      return false;
    }
  }
  KV的预读逻辑如下
  public boolean nextKeyValue() throws IOException, InterruptedException {
    if (!hasMore) {
      key = null;
      value = null;
      return false;
    }
    //读取新KEY的时候firstValue为真,此时nextKeyIsSame为假
    //当读取相同KEY的非首条记录时,firstValue会置为假
    firstValue = !nextKeyIsSame;
    //将KV读取到buffer中
    DataInputBuffer next = input.getKey();
    currentRawKey.set(next.getData(), next.getPosition(), 
                      next.getLength() - next.getPosition());
    buffer.reset(currentRawKey.getBytes(), 0, currentRawKey.getLength());
    key = keyDeserializer.deserialize(key);
    next = input.getValue();
    buffer.reset(next.getData(), next.getPosition(), next.getLength());
    value = valueDeserializer.deserialize(value);
    //再读取一条,用于判断下一条的KEY是否相同,来设置nextKeyIsSame
    hasMore = input.next();
    if (hasMore) {
      next = input.getKey();
      nextKeyIsSame = comparator.compare(currentRawKey.getBytes(), 0, 
                                         currentRawKey.getLength(),
                                         next.getData(),
                                         next.getPosition(),
                                         next.getLength() - next.getPosition()
                                         ) == 0;
    } else {
      nextKeyIsSame = false;
    }
    inputValueCounter.increment(1);
    return true;
  }
KEY判断完毕,如果确定还有数据则进入到自定义的reduce函数中,这里我们以WordCount为例,由于函数中会对同一个KEY的相同VALUE进行迭代,因此会传入Iterable(第二个参数),该参数封装了org.apache.hadoop.mapreduce.ReduceContext.ValueIterator
	protected void reduce(Text key, java.lang.Iterable<IntWritable> arg1,
			Context context) throws IOException, InterruptedException {
		Iterator<IntWritable> iterator = arg1.iterator();//获得迭代器
		int sum = 0;
		while (iterator.hasNext()) {//判断是否有下一个VALUE
			sum += iterator.next().get();//自定义操作
		}
		context.write(key, new IntWritable(sum));//写出操作
	};	
在对VALUE的迭代中每读取一次VALUE,都会判断下一个VALUE是否相同,以设置nextKeyIsSame的值,当相同KEY的VALUE有多条时,一旦nextKeyIsSame为假,那么证明需要处理下一个KEY了。
  protected class ValueIterator implements Iterator<VALUEIN> {
    @Override
    public boolean hasNext() {
      return firstValue || nextKeyIsSame;
    }


    @Override
    public VALUEIN next() {
      // 如果为首条记录则直接返回,注意此时firstValue状态变化
      if (firstValue) {
        firstValue = false;
        return value;
      }
      // if this isn't the first record and the next key is different, they
      // can't advance it here.
      if (!nextKeyIsSame) {
        throw new NoSuchElementException("iterate past last value");
      }
      // 读取下一条KV,具体逻辑见上面nextKeyValue的分析
      try {
        nextKeyValue();
        return value;
      } catch (IOException ie) {
        throw new RuntimeException("next value iterator failed", ie);
      } catch (InterruptedException ie) {
        // this is bad, but we can't modify the exception list of java.util
        throw new RuntimeException("next value iterator interrupted", ie);        
      }
    }


    @Override
    public void remove() {
      throw new UnsupportedOperationException("remove not implemented");
    }
    
  }
  当reduce阶段输出时,如果目的地是HDFS,则会直接写入,此时HDFS相当于服务端,reduce任务相当于客户端,也是调用FSDataOutputStream来写出的,这里就不再多分析了。

关于java.util.NoSuchElementException错误的一则例子

写了一个从A文件复制到B文件的例子,其中要求去掉重复的行。于是想到了Set,这本来是很容易的事情,结果在向外写数据时抱错java.util.NoSuchElementException网络上反复查证也...
  • ppact
  • ppact
  • 2007年07月13日 15:14
  • 102568

Hadoop源码篇--Reduce篇

声明~由于不同博客平台代码阅读样式不一样,所以欢迎访问 本人博客园地址:Hadoop源码篇--Reduce篇 个人网页博客地址:Hadoop源码篇--Reduce篇  带给你不一样的阅读体验...
  • LHWorldBlog
  • LHWorldBlog
  • 2018年01月10日 21:23
  • 80

Hadoop MapReduce之ReduceTask任务执行(二)

reduce任务为获得map的输出要和TaskTracker 通信以获得map的完成情况,负责这个工作的是GetMapEventsThread。线程运行时会通过TT的代理调用TaskUmbilical...
  • lihm0_1
  • lihm0_1
  • 2013年11月29日 16:12
  • 1504

Hadoop MapReduce之ReduceTask任务执行(五)

本节分析ReduceTask的最后一个阶段:reduce,经历了copy、sort后,reduce的输入数据就准备好了,reduce数据输入由Reducer.Context提供,该Context封装了...
  • lihm0_1
  • lihm0_1
  • 2013年12月05日 15:30
  • 1549

hadoop groupingComparator 与 secondary sort

《hadoop权威指南》里的例子:有许多气象记录,需要找出每年的最高温度,通过secondary sort实现。(这个任务其实简单的map-reduce就可以完成,这里只是为了演示secondary ...
  • groovy2007
  • groovy2007
  • 2015年03月18日 12:15
  • 819

hadoop的mapreduce任务的执行流程

hadoop2.x的三大核心:mapreduce 、hdfs以及yarn ,其中核心之一mapreduce,利用了分而治之的思想,Map(映射)和 Reduce(归约),分布式多处理然后进行汇总的思想...
  • qq_20641565
  • qq_20641565
  • 2017年03月23日 20:25
  • 855

Hadoop MapReduce之ReduceTask任务执行(一)

reduce执行流程经历三个阶段:copy、sort、reduce,在第一阶段reduce任务会把map的输出拷贝至本地,通过线程MapOutputCopier,该线程通过http协议将map输出拷贝...
  • lihm0_1
  • lihm0_1
  • 2013年11月28日 15:41
  • 1354

opencv中HOG源码学习笔记

1、opencv中HOGstruct CV_EXPORTS_W HOGDescriptor { public: enum { L2Hys=0 }; enum { DEFAULT_NLEVELS=64 ...
  • yiting52
  • yiting52
  • 2014年05月14日 15:47
  • 533

MapReduce源码分析之MapTask分析(二)

MapReduce源码分析之MapTask详解的后半段文章。在分析过程中我们知道了MapTask是如何使用循环缓存区管理数据,知道了数据在缓存不下是如何做spill处理的,spill输出的数据格式,c...
  • chlaws
  • chlaws
  • 2014年08月04日 22:21
  • 4879

Hadoop MapReduce之ReduceTask任务执行(三)

在reduce端的文件拷贝阶段,会将数据放入内存或直接放入磁盘中,如果文件全部拷贝完再进行合并那样必然降低作业效率,所以在拷贝进行到一定阶段,数据的合并就开始了,负责该工作的有两个线程:InMemFS...
  • lihm0_1
  • lihm0_1
  • 2013年12月02日 14:23
  • 1144
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Hadoop MapReduce之ReduceTask任务执行(五)
举报原因:
原因补充:

(最多只允许输入30个字)