我对Map端spill的理解
一、先看简单理解
对于hadoop的map端配置项"mapreduce.task.io.sort.mb"和"mapreduce.map.sort.spill.percent"应该都比较熟悉了,如图解释(http://hadoop.apache.org/docs/current/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html):
翻译成汉语的解释也有不少,随便粘一个"mapreduce.task.io.sort.mb 任务内部排序缓冲区大小,默认100","mapreduce.map.sort.spill.percent Map阶段溢写文件的阈值(排序缓冲区大小的百分比),默认0.8,也就是80%"。这些内容一点都不难理解,就是map的结果先放入缓冲区(其实先序列化),当缓冲区的数据量达到阈值时(默认100M * 0.8 = 80M),溢出行为会在一个后台线程执行开始spill操作。
二、发现问题
问题的核心在于mapreduce.map.sort.spill.percent这个配置。
前两天浏览官网(http://hadoop.apache.org/docs/current/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html)时在上述两条配置的说明下面还有两条注意事项,其中主要疑问在第一条,如图:
只看第一条就行,我开始对这条英文的理解比较模糊,于是上网找了一些官网的翻译(http://blog.csdn.net/u011812294/article/details/53379338?locationNum=8&fps=1),如图:
虽然我对这段英文理解的比较模糊,但是也能看出这个翻译是明显错误的(只是就事论事,没有批评作者的意思,毕竟官网那么多英文都大体翻译了过来已经很了不起了,谁都有没有理解不是很透彻的地方,而且好多内容我都是看这篇翻译弄懂的),那到底会不会起额外的线程呢,spill到磁盘的数据是只有percent * buffer的数据量呢还是另有门道呢?这算是"疑问一"。于是我就又看了官网的mapred-default.xml文件对这个配置的说明,如图:
这解释前半部分没什么说的,后半部分透露出一个信息,当percent小于0.5的时候spill到磁盘的数据量有可能会大于percent * buffer,这又是为什么呢?这算是"疑问二"。下面就是我通过大量的请教别人和上网查资料之后,对这两个问题的解释。
三、解释两个疑问
对我帮助最大的应该是这篇文章"http://www.tuicool.com/articles/7FNN32",对此作者表示由衷的感谢。
要解释这两个疑问需要用到再稍微深一层的知识,我再这里只对深一层的东西做一个简单的抽象,能解决问题就行,例如实际有3个环形缓冲区,我只抽象成一个。
简单来说,map的输出到一个缓存区(中间还有个序列化过程不讨论),这个环形缓冲区有三个索引(或者指针),分别叫kvStart、kvEnd、kvIndex。map结果每进来一个keValue对,kvIndex更新一次,也就是始终标识下一个可用的地址,此时还没达到阈值,没有开始spill,kvStart=kvEnd,指向标识当spill开始时的起始位置,然后,阈值到了,后台开启一个spill线程,此时,kvStart暂时不变,而对kvEnd进行重新赋值,kvEnd=kvIndex,然后kvIndex不受影响继续随着map结果的写入而不断更新直到缓冲区满了为止。此时,spill要处理的数据其实已经确定了,就是kvStart到(kvEnd-1)这区间的数据进行溢写,此过程kvEnd正常情况不变,而每溢写成功一条数据kvStart好像是更新一次,直到最后spill成功时kvStart=kvEnd,为下一次的spill做准备。
上一段描述的是一般情况下的spill过程抽象,但是还是不能解释我提的两个疑问,其实从英文解释可以看的出我的两个疑问是些另外的情况,而这另外的情况指的就是percent小于0.5的可能会发生的情况。下面举例子说明这种情况。
例如mapreduce.map.sort.spill.percent=0.33,当缓冲区第一次达到阈值时,启动一个后台spill线程开始正常的溢写操作,由于缓冲区没满,map结果继续写入缓冲区(这一过程称为Collect),当又一个0.33*buffer被写入之后,便再次触发溢写过程,但是此时不会另外启动一个spill线程,不过呢kvEnd会被重新赋值,kvEnd被重新赋值之后呢,kvStart要到达新的kvEnd时才能结束,这样两次触发一共要处理的数据总量就是2 * 0.33 * buffer=0.66 * buffer了(当然也有可能出现3次出发,结果0.99 * buffer的情况),但是多次触发很明显只能是percent<0.5的情况,因为当percent>0.5时剩余buffer即使满了也达不到0.5,不能触发。
这样就很好的解释了这段英文"Note that collection will not block if this threshold is exceeded while a spill is already in progress, so spills may be larger than this threshold when it is set to less than .5"
还有一句英文"and the remainder of the buffer is filled while the spill runs, the next spill will include all the collected records, or 0.66 of the buffer, and will not generate additional spills",我感觉这还真有点灵活翻译理解的味道,关键字在于对"or"的理解,我认为翻译成"或者"并不是很恰当,而应该翻译成"也就是",换句话说,"0.66"就是对前面"all the collected records"用一种说法做的说明,而不是指的两种情况,当然"0.66"更不是指的percent=0.66了。至此,两个疑问都解释清楚了,当然底层模型我抽象的比较简单,要了解真正的过程看对我帮助最大的那篇文章,解释的非常详细,不过内容也十分多,需要自己找。
四、对spill过程中的锁做一个简单的摘抄,也来自文章"http://www.tuicool.com/articles/7FNN32"
两种信号:spillDone和spillReady,它们的逻辑如下:
1)对于写线程来说,如果写满了,就调用spillDone.await等待spillDone信号;否则不断往缓冲区里面写,到了一定程度,就发送spillReady.signal这个信号给读线程,发完这个信号后如果缓冲区没满,就释放锁继续写(这段代码无需锁),如果满了,就等待spillDone信号;
2)对于读线程来说,在平时调用spillReady.await等待spillReady这个信号,当读取之后(此时写线程要么释放锁了,要么调用spillDone.await在等待了,读线程肯定可以获得锁),则把锁释放掉,开始Spill(这段代码无需锁),完了读线程再次获取锁,修改相应参数,发送信号spillDone给写线程,表明Spill完毕。
要看更详细信息还是看这篇文章"http://www.tuicool.com/articles/7FNN32"。
我对Map端spill的理解的更多相关文章
- Hadoop on Mac with IntelliJ IDEA - 10 陆喜恒. Hadoop实战(第2版)6.4.1(Shuffle和排序)Map端 内容整理
下午对着源码看陆喜恒. Hadoop实战(第2版)6.4.1 (Shuffle和排序)Map端,发现与Hadoop 1.2.1的源码有些出入.下面作个简单的记录,方便起见,引用自书本的语句都用斜体表 ...
- Hadoop2.4.1 MapReduce通过Map端shuffle(Combiner)完成数据去重
package com.bank.service; import java.io.IOException; import org.apache.hadoop.conf.Configuration;im ...
- 项目中Map端内存占用的分析
最近在项目中开展重构活动,对Map端内存尽量要省一些,当前的系统中Map端内存最高占用大概3G左右(设置成2G时会导致Java Heap OOM).虽然个人觉得占用不算多,但是显然这样的结果想要试 ...
- hadoop的压缩解压缩,reduce端join,map端join
hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...
- MapReduce在Map端的Combiner和在Reduce端的Partitioner
1.Map端的Combiner. 通过单词计数WordCountApp.java的例子,如何在Map端设置Combiner... 只附录部分代码: /** * 以文本 * hello you * he ...
- Hive Map 端OOM 异常
怪异现象:数据量不大,且不是Reduce端OOM,是Map端OOM Map Task运行的时候数据流中包含了非法字符例如:EOF.NOP等东西,导致BufferedReader读取和StreamDec ...
- Hadoop基础-Map端链式编程之MapReduce统计TopN示例
Hadoop基础-Map端链式编程之MapReduce统计TopN示例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.项目需求 对“temp.txt”中的数据进行分析,统计出各 ...
- hadoop map端的超时参数
目前集群上某台机器卡住导致出现大量的Map端任务FAIL,当定位到具体的机器上时,无法ssh或进去后terminal中无响应,退出的相关信息如下: [hadoop@xxx ~]$ Received d ...
- 项目中Map端数据处理不均匀性分析
Map任务的不均匀性 最近发现Map端数据越来越不均匀,而处理输入的数据,写到本地磁盘的数据量都差不多,我们随便拿出来两个attempt任务(当前map数量为64个),33和45,33的counter ...
随机推荐
- [置顶] SQL注入安全分析
(一) 应用环境列表 网络互联设备操作系统 序号 操作系统名称 设备名称 脆弱性 1 IOS_路由器_内部_1 route1 2 IOS_路由器_VPN_1 路由器_VPN_1 3 IOS ...
- activity的android:name所指的Activity实现类的简写问题
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package=" ...
- C语言中判断int,long型等变量是否赋值的方法
博主这段时间在写一些C程序的代码,由于以前对C不是了解很多,故遇到很多瓶颈,当然,其中也有很多有趣的方法可以利用以解决这些难题,下面这个问题就是博主遇到的一个麻烦. 声明了 int ,long 型等局 ...
- The Event System
The Event System 在Qt中,事件是继承了虚拟类QEvent的对象,它代表了程序所发生的事情或者程序需要知道的一个外部活动的结果.事件可以被任意 QObject子类的实例接收和处理,是与 ...
- 工作流--JBPM核心服务及表结构
一. 使用JBPM开发工作流的一般流程 1. jBPM的运行需要数据库的支持,因此系统设计时要选定所用数据库.只要是Hibernate支持的数据库,jBPM就支持.数据库的初始化 ...
- 打破惯性思维:聊聊一次debug
最近公司的新需求中要增加活动营销,整个组的人都被安排去研究某成熟产品的实现.我也认真地在看webService部分的实现,发现了一个诡异的10614端口的请求. 代码如下图: 这是一段服务端发请求验证 ...
- 关于SQL 数据表中的密码加密
首先,都知道一个字节(byte)等于八位二进制数.在数据表中将密码字段设置为binary类型,再结合哈希散列运算可以实现密码加密. 下面介绍下binary 和 varbinary: binary 和 ...
- 微信小程序开源项目库集合
UI组件 weui-wxss ★852 - 同微信原生视觉体验一致的基础样式库 Wa-UI ★122 - 针对微信小程序整合的一套UI库 wx-charts ★105 - 微信小程序图表工具 wema ...
- elasticsearch查询模板
{ "from":#from#, "size":#size#, "_source":#source#, "query": ...
- IOS GCD图片数据异步下载,下载完成后合成显示
关于GCD使用详解,请看我的上一篇blog:http://www.cnblogs.com/xin-lang/p/6278606.html 前段时间遇到个需要异步下载,下载完成后再组合显示的东西.这里我 ...