MapReduce之collect过程分析
来源:互联网 发布:c语言的未来 编辑:程序博客网 时间:2024/06/04 01:09
我们知道map任务在处理完一个key/value之后,就会进行collect操作:分区,排序,溢写等操作,这些操作都属于collect操作。
我们在map方法中,处理完一对key:value,就会调用write方法,本质上就是调用MapTask初始化的NewOutputCollector的write方法, 进而调用collect方法,开始collect流程
一 计算key落在哪一个分区
再调用collect方法的时候,会传入当前的key 和 value。并且传入当前key所在的分区. 那么这里分区的算法是什么呢?
#如果没有设置reduce任务的数量,那么默认就一个reduce 任务。
那么分区无论多少key:value对都只在一个分区0上。
#如果reduce任务数量大于 1,那么就会用用户在job中设置的Partitioner来计算分区,如果没有设置就使用默认的分区HashPartitioner
#默认HashPartitioner的算法就是(key.hashcode& Integer.MAX_VALUE) % reduce 任务数 = 当前key位于哪一个分区
二 环形缓冲区介绍
最后通过调用MapOutputBuffer#collect方法,正式进入collect流程:
MapOutputBuffer使用一个内存缓冲区,将结果暂时存储在这里。当缓冲区达到一定阀值比例,默认80%的时候,再将缓冲区数据写入磁盘。
一般的数据缓冲区有多种实现,常见的有:
=>单向缓冲区:生产者向缓冲区写数据,写满后一次性写到磁盘,但是存在性能不高的情况,因为不能支持同时读写数据。即所谓我写你就不能读,写满了你才能读。读完了你才能继续写。
=>双缓冲区:一个用于写数据,一个用户读,比单向稍微提高一点新能,只能在一定程度支持并发读写。即所谓我先写第一个,写满之后,开始读取,然后新来的请求开始写第二个;第二个写满后,第一个已经读取完后,有可以在第一个上面写
=>环形缓冲区:当缓冲区使用达到阀值,便开始向磁盘写数据,同时生产者仍然可以不断向剩余空间写数据,进而真正到达读写并行。
MapOutputBuffer通过SpillThread线程将环形缓冲区达到80%的时候,就将数据写入临时文件,等到所有数据处理完毕,对所有临时文件进行一次合并生成一个最终文件
首先我们需要理解几个概念:
缓冲区kvbuffer: 其实是一个字节数组,初始容量是指定的每一个map任务的内存数量>> 20
kvmeta:根据kvbuffer字节数组构造的一个IntBuffer。它主要是用于存储key-value的索引信息,包括key开始位置,value开始位置,partition信息,以及value长度
kvmeta同样是存储在kvbuffer里的,也就是说kvbuffer除了要存储真正的key-value数据,还要存储其索引信息,所以kvbuffer这个缓冲区可以理解为它包含两个部分:数据区和索引区
数据区和索引区是相邻的但是不重复的两个区间,有一个分界点equator(赤道)来分割,初始equator的位置是0。数据存储方向是向上增长,索引存储方向是向下增长
kvstart:索引记录开始的位置
kvindex:下一个可以写索引记录的位置,类似于buffer中的position
kvend:索引记录结束的位置
在开始的时候kvstart=kvend=kvindex
kvend在spill的时候 kvend=kvindex, spill结束,就会kvend=kvstart
bufstart:写入key-value的开始位置
bufend:写入key-value的结束位置
bufindex:下一个要写入key-value的位置
bufvoid:缓冲区结束位置,默认和缓冲区长度一致。写到这儿,表示不能继续读写
数据区和索引取都始终闷着头一直跑,那么钟会有碰头的那一天,碰头之后,再重新开始或者移动内存就比较麻烦了。所以在spill结束的时候调用resetSpill方法,将kvbuffer中剩余的空间的中间位置设置为新的分界点equator。
我们知道当kvbuffer达到了使用阀值,我们就需要开始进行spill操作,spill操作是由一个线程类SpillThread来完成的,它会调用sortAndSpill方法:
1先计算文件大小
2获取写入本地文件的名字,比如output/spill0.out
3使用快速排序对缓冲区kvbuffer中间[bufstart,bufend)之间的数据排序:
#现根据partition升序排序
#然后再对key进行排序
4构建IFile.write,传入输出流,输出到指定文件中,在这里支持压缩
5如果用户设置了combiner,在这里可能会启用combiner,则对每一个分区中的数据进行一次聚合操作
6将元数据写入SpillRecord,如果内存中索引大于1M,则溢写到out
Put/spillN.out.index文件中
7spill结束调用reset方法,重新设置spill
- MapReduce之collect过程分析
- MapReduce任务执行过程研究之Collect过程
- 分析MapReduce执行过程
- MapReduce Shuffle过程分析
- 分析MapReduce执行过程
- MapReduce处理过程分析
- MapReduce Shuffle过程分析
- MapReduce之shuffle过程
- MapReduce 之shuffle过程
- MapReduce 运行过程源代码分析
- 深入分析MapReduce shuffle过程
- hadoop mapreduce详细过程分析
- Hadoop之MapReduce 分析
- MapReduce之Shuffle过程详述
- MapReduce之Shuffle过程详解
- mapreduce源码分析之JobTracker
- Hadoop之MapReduce WordCount分析
- Hadoop之MapReduce程序分析
- Mysql如何新建一个服务和移除所新建的服务
- CNN优化指南
- spring boot 快速入门链接
- 取出数据库中BASE64编码后的图片二进制流数据显示在JSP页面上
- dva+react+antd
- MapReduce之collect过程分析
- openwrt中搭建VRRP
- Android_BottomTabBar
- HR服务是大金矿,中国几千家掘金企业为啥出不了一家独角兽?
- 零食招商代理,没有销量何来利润?
- “阿里云之父”王坚:硅谷不应当成为我们的天花板 | 腾讯2017年Q3营收同比增61%
- MATLAB中plot的用法
- C++基础代码—20余种数据结构和算法的实现
- 网易2017秋招编程题:暗黑的字符串 [python]