随手记点-mapreduce4

1.在map处理的过程中有几个线程?各个线程又分别完成了什么任务?

答:mainThread:主要任务是获取(k,v)数据,map处理数据,paritition分区,seralize序列化,结果写入缓冲区。
spillThread:当mainThread发现内存缓冲区的占用百分比已经达到某个临界值(默认为0.8)时就会唤醒spillThead线程。spillThead线程把内存缓冲区里的数据sortAndSpill到硬盘上,每次spill都会溢写一个文件(如果有combine,则先进行combine操作,再写入硬盘中),这样会产生多个溢写文件到硬盘上。


3.map的输出是如何管理的?

答:map的输出是先放到一个环形的内存缓冲区mapoutputbuffer中。写入缓冲区的方法是之前提到的collect,内存缓冲区的代码是 kvnetx=(kvindex+1)%kvoffsets.length。数据在mapoutputbuffer中是一个两级索引结构,包括了kvoffsets和kvindices。kvoffsets可以当作是引用,剩下的作为对象的数组。从缓冲区取出数据有两种方法,一是在sortAndSpill方法中直接从内部数组中读取,另外还可以使用combine,MRResultIterator将缓冲区内的数据组织成KV对的读取。


4.Shuffle中的Spill具体过程是怎样的?

答:如果内存缓冲区所占空间达到一定的阈值,就需要把内存缓冲区的数据spill写入硬盘中,以免造成过大的内存开销。SpillThread调用的是sortAndSpill()方法,其中sort是先使用QuickSort()对内存缓冲区中需要spill的数据进行排序,然后使用write写入硬盘中。


5.为什么要排序?如何实现排序的?

答:排序的目的是先按照partition进行排序,每个partition内key有序,排序是shuffle的关键所在。快排需要两个操作,分别是比较大小和互换位置。下面是实现排序的程序:

//排序使用的是QuickSort
      sorter = ReflectionUtils.newInstance(
                  job.getClass("map.sort.class", QuickSort.class, IndexedSorter.class), job);
//比较函数
    public int compare(int i, int j) {
      final int ii = kvoffsets[i % kvoffsets.length];
      final int ij = kvoffsets[j % kvoffsets.length];
      // sort by partitionif (kvindices[ii + PARTITION] != kvindices[ij + PARTITION]) {
        return kvindices[ii + PARTITION] - kvindices[ij + PARTITION];
      }
      // sort by keyreturn comparator.compare(kvbuffer,
          kvindices[ii + KEYSTART],
          kvindices[ii + VALSTART] - kvindices[ii + KEYSTART],
          kvbuffer,
          kvindices[ij + KEYSTART],
          kvindices[ij + VALSTART] - kvindices[ij + KEYSTART]);
    }
//交换函数
    public void swap(int i, int j) {
      i %= kvoffsets.length;
      j %= kvoffsets.length;
      int tmp = kvoffsets[i];
      kvoffsets[i] = kvoffsets[j];
      kvoffsets[j] = tmp;
    }

6.内存缓冲区是怎么设计的?

答:内存缓冲区的设计有两个目标,一个是可以存储不定长的数据,另一个是可以完成对这些数据按照partition和key进行排序。对于不定长的数据,一般是通过建立(起始位置,长度)的索引来指示数据的位置,也就是例如(startOfPartition, lengthOfPartition, startOfKey, lengthOfKey, startOfValue, lengthOfValue)的索引。排序则是将这个作为单位来移动的。在MapOutputBuffer中利用kvindices来进行索引,具体的(k,v)的值存在kvbuffer中。


7.内存缓冲区中key和value分别是怎样读取的?

答:key的读取

public DataInputBuffer getKey() throws IOException {
        final int kvoff = kvoffsets[current % kvoffsets.length];
        keybuf.reset(kvbuffer, kvindices[kvoff + KEYSTART],
                     kvindices[kvoff + VALSTART] - kvindices[kvoff + KEYSTART]);
        return keybuf;
      }

kv在kvbuffer中是连续存放的,即kvkvkv… 。key虽然在理论上也存在写入时不连续性的问题,但在mapreduce中通过reset()函数来保证key是连续的,也是为了后面按照key进行排序做准备。(value的起始地址-key的起始地址)就是key的值。

value的读取

public DataInputBuffer getValue() throws IOException {
      getVBytesForOffset(kvoffsets[current % kvoffsets.length], vbytes);
      return vbytes;
    }
    private void getVBytesForOffset(int kvoff, InMemValBytes vbytes) {
      final int nextindex = (kvoff / ACCTSIZE == (kvend - 1 + kvoffsets.length) % kvoffsets.length)
        ? bufend : kvindices[(kvoff + ACCTSIZE + KEYSTART) % kvindices.length];
      int vallen = (nextindex >= kvindices[kvoff + VALSTART])
        ? nextindex - kvindices[kvoff + VALSTART] : (bufvoid - kvindices[kvoff + VALSTART]) + nextindex;
      vbytes.reset(kvbuffer, kvindices[kvoff + VALSTART], vallen);
    }

(下一个key的起始地址-value的起始地址)之间的数据就是value的值。但因为缓冲区是环形的,虽然可以通过reset()来保证key的连续性,但value的连续性无法保证。InMemValBytes这个类就是为了解决value不连续的问题。


8.combine和merge的关系?

答:如果用户设置了combine,则在进行spill的同时会进行combine,combine是将过多的spill文件进行合并的过程,combine的输入数据是还没有写入硬盘的spill文件,即输入数据在内存中,输出是把spill文件进行合并后输出到硬盘,也就是说spill中间执行。combine从缓冲区中把文件读取出来,进行处理,写入文件。


9.为什么要merge?merge过程是怎样进行的?merge和spill有什么关系?

答:spill的过程会执行多次,导致会产生多个溢写文件。如果直接将这么多的溢写文件交给后续的reducer端去处理,必然会产生大量的磁盘IO开销,所以通过merge把文件数量减少。merge的过程是将多个溢写文件合并成一个文件,并且保持按照partition和key有序排列。merge处理的spill完成后的文件,是减少spill溢写文件总量的过程。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值