﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-实验室宅男的一亩三分地-随笔分类-hadoop</title><link>http://www.cppblog.com/whspecial/category/19559.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 27 Oct 2013 15:52:56 GMT</lastBuildDate><pubDate>Sun, 27 Oct 2013 15:52:56 GMT</pubDate><ttl>60</ttl><item><title>跨机房的hadoop集群</title><link>http://www.cppblog.com/whspecial/archive/2013/10/27/203940.html</link><dc:creator>whspecial</dc:creator><author>whspecial</author><pubDate>Sun, 27 Oct 2013 15:28:00 GMT</pubDate><guid>http://www.cppblog.com/whspecial/archive/2013/10/27/203940.html</guid><wfw:comment>http://www.cppblog.com/whspecial/comments/203940.html</wfw:comment><comments>http://www.cppblog.com/whspecial/archive/2013/10/27/203940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/whspecial/comments/commentRss/203940.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/whspecial/services/trackbacks/203940.html</trackback:ping><description><![CDATA[<div><p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">这是来自于阿里技术嘉年华的一个分享，因为在百度也考虑过类似的事情，所以听得比较有感悟，这里把相关内容整理一下。</span></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">首先尊重版权，还是把原链接和作者贴上：</span></p>  <p style="line-height:150%"><a href="http://adc.alibabatech.org/carnival/history/schedule/2013/detail/main/286?video=0">http://adc.alibabatech.org/carnival/history/schedule/2013/detail/main/286?video=0</a></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">来自于阿里吴威工程师的分享</span></p>  <p style="line-height:150%">&nbsp;</p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">首先需要说明一点，跨机房</span>hadoop<span style="font-family:宋体;">可能应用场景并不是很多，国内像</span>BAT<span style="font-family:宋体;">这种巨头也许需要，但是大部分的中小公司也许并不需要这个，也许这是个屠龙之技，呵呵。</span></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">把这个问题分三段来讲，第一段是问题出现的背景，第二段是解决该问题的难点，第三段是最终的解决方案。</span></p>  <p style="margin-left:36.0pt;text-indent:-36.0pt;line-height:150%;"><strong>（一）&nbsp;</strong><strong><span style="font-family:宋体;">背景：</span></strong></p>  <p style="line-height:150%"><span style="font-family:宋体;">先要看下为什么需要做一个跨机房的大集群？</span></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">大集群的优点在于数据管理和授权容易（这个问题在一个多部门的大公司还是很重要的）；跨部门的使用数据容易，无需重复拉取数据。</span></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">在集群达到一定规模时，单机房（机房内的容量是有限的）已经无法满足集群的需求了，要想一劳永逸的解决问题，需要建设一个跨机房的</span>hadoop<span style="font-family:宋体;">集群。</span></p>  <p style="line-height:150%"><strong><span style="font-family:宋体;">（二）技术挑战：</span></strong></p>  <p style="line-height:150%"><strong>2.1 NameNode</strong><strong><span style="font-family:宋体;">的性能问题：</span></strong></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">在管理一个巨大的</span>hadoop<span style="font-family:宋体;">集群时，由于原始的</span>Namenode<span style="font-family:宋体;">是单节点，因此会成为一个性能瓶颈，遇到的性能问题主要包括两方面：存储容量问题（存储元数据）和计算压力（处理</span>rpc<span style="font-family:宋体;">请求，修改内存树时候需要全局锁）问题。</span></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">其中存储容量问题可以依赖内存的垂直扩展来解决，但是计算压力却很难通过提升硬件来解决（因为目前厂商的主要发展方向是多核，而非提高主频）</span></p>  <p style="line-height:150%"><strong>2.2</strong><strong><span style="font-family:宋体;">机房之间的网络限制：</span></strong></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">机房之间的网络永远是个硬件条件的限制，跨机房的网络传输带来了数据延时和带宽限制：</span></p>  <p style="margin-left:39.0pt;text-indent:-18.0pt;line-height:150%;">1，&nbsp;<span style="font-family:宋体;">延时一般是在</span>10ms<span style="font-family:宋体;">之内，而</span>hadoop<span style="font-family:宋体;">上大部分运行的是离线作业，基本可接受</span></p>  <p style="margin-left:39.0pt;text-indent:-18.0pt;line-height:150%;">2，&nbsp;<span style="font-family:宋体;">带宽限制的问题比较大，因为单机房内的点对点带宽一般是在</span>1Gbps<span style="font-family:宋体;">，而机房之间的带宽确在</span>20Mbps<span style="font-family:宋体;">左右，非常有限。</span></p>  <p style="line-height:150%"><strong>2.3</strong><strong><span style="font-family:宋体;">资源组之间的管理</span></strong></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">每个部门可以看做一个资源组，它们可能会互相使用对方的数据，因此如何规划计算和存储的位置就很重要，否则会在多个机房之间出现大量的数据拷贝。</span></p>  <p style="line-height:150%"><strong><span style="font-family:宋体;">（三）解决方案：</span></strong></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">先看下整个跨集群</span>hadoop<span style="font-family:宋体;">的架构图：</span></p>  <p style="line-height:150%"><img src="http://www.cppblog.com/images/cppblog_com/whspecial/QQ图片20131027233042.jpg" width="558" height="315" alt="" /><br /></p>  <p style="line-height:150%">&nbsp;</p>  <p style="text-indent:18.0pt;line-height:150%"><span style="font-family:宋体;">重点介绍里面三点，也就是和上面三个问题相对应的：</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;line-height:150%;">1，&nbsp;<span style="font-family:宋体;">可以看到这里画出了两个</span>NN<span style="font-family:宋体;">（</span>namenode<span style="font-family:宋体;">），它们实际上还是属于一个</span>hadoop<span style="font-family:宋体;">集群，这是业界里的一个解决方案：</span>HDFS Fedaration<span style="font-family:宋体;">，它为了解决元数据节点性能问题；</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;line-height:150%;">2，&nbsp;<span style="font-family:宋体;">可以看到这里有一个</span>cross node<span style="font-family:宋体;">节点，它是用来在两个机房之间同步数据的，它的设计考虑到了机房间的网络限制；</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;line-height:150%;">3，&nbsp;<span style="font-family:宋体;">最后是</span>groupA<span style="font-family:宋体;">、</span>groupB<span style="font-family:宋体;">，这是为了解决数据产出方和使用方关系来用的。</span></p>  <p style="line-height:150%"><strong>3.1 Federation</strong></p>  <p style="text-indent:18.0pt;line-height:150%">Federation<span style="font-family:宋体;">相关资料见：</span></p>  <p style="text-indent:18.0pt;line-height:150%"><a href="http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/Federation.html#HDFS_Federation">http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/Federation.html#HDFS_Federation</a></p>  <p style="text-indent:18.0pt;line-height:150%"><img src="http://www.cppblog.com/images/cppblog_com/whspecial/QQ图片20131027233052.jpg" width="547" height="381" alt="" /><br /></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">为了水平扩展</span>Namenode<span style="font-family:宋体;">，</span>federation<span style="font-family:宋体;">使用了多个互相独立的</span>namenode<span style="font-family:宋体;">。它们之间互相不需要通信，每个</span>datenode<span style="font-family:宋体;">需要向全部</span>namenode<span style="font-family:宋体;">注册并发送信息。</span></p>  <p style="text-indent:21.0pt;line-height:150%">BlockPool<span style="font-family:宋体;">是属于一个</span>namenode<span style="font-family:宋体;">的</span>block<span style="font-family:宋体;">集合，每个</span>blockpool<span style="font-family:宋体;">之间也是互相独立的。</span></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">在</span>federation<span style="font-family:宋体;">里，有一个需要关注的问题，就是多个</span>namenode<span style="font-family:宋体;">的地址如何对用户进行透明？它采用的解决方案是目录树挂载的方案（社区有个</span>viewFS<span style="font-family:宋体;">，应该就是为了解决这个问题）：熟悉</span>linux<span style="font-family:宋体;">或者</span>nfs<span style="font-family:宋体;">的朋友应该都知道</span>mount<span style="font-family:宋体;">这个概念，目录树挂载就是这个意思。</span></p>  <p style="text-indent:21.0pt;line-height:150%"><span style="font-family:宋体;">不过使用目录树挂载也存在着一个问题，就是各个子目录下的存储资源需要人为的介入管理，不能出现严重的不均。</span></p>  <p style="line-height:150%"><strong>3.2 crossNode</strong></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">机房间的网络限制要求不能出现大规模、长时间的数据拷贝，需要一个专门管理机房间数据拷贝的进程，叫做</span>crossNode<span style="font-family:宋体;">。它是独立部署的一个节点，和元数据节点是分离的。</span></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">它能提供的功能概括来说主要包括以下三点：</span></p>  <p style="margin-left:39.0pt;text-indent:-18.0pt;line-height:150%;">a）&nbsp;<span style="font-family:宋体;">根据预置的跨机房文件，进行数据拷贝</span></p>  <p style="margin-left:39.0pt;text-indent:-18.0pt;line-height:150%;">b）&nbsp;<span style="font-family:宋体;">处理实时的数据拷贝请求</span></p>  <p style="margin-left:39.0pt;text-indent:-18.0pt;line-height:150%;">c）&nbsp;<span style="font-family:宋体;">进行跨机房的数据流量控制</span></p>  <p style="margin-left:21.0pt;line-height:150%"><span style="font-family:宋体;">如何得知跨机房文件列表？</span></p>  <p style="line-height:150%">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-family:宋体;">由于离线任务基本都是定时触发的，可以根据对历史作业的分析来形成一个跨机房文件列表</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;line-height:150%;"><strong>3.3<span style="font-weight: normal; font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp; </span></strong><strong><span style="font-family:宋体;">资源组之间的管理</span></strong></p>  <p style="text-indent:18.0pt;line-height:150%"><span style="font-family:宋体;">各个资源组之间存在数据的依赖，我们希望通过资源组管理，能实现大部分任务在本机房内产出数据，只有少量跨机房产出数据；大部分任务读取本机房的数据副本，只有少量跨机房读取数据。</span></p>  <p style="text-indent:18.0pt;line-height:150%"><span style="font-family:宋体;">为了标识资源组之间的数据依赖性，定义一个资源组之间的距离概念：一个资源组访问另一个资源组的数据量越多，则两者的距离越近，应该将距离接近的资源组放在同一个机房内。</span></p>  <p style="text-indent:18.0pt;line-height:150%"><span style="font-family:宋体;">为了让计算和产出尽可能地靠近，使用一个</span>MRProxy<span style="font-family:宋体;">，对于不同类型的任务做不同处理：</span></p>  <p style="margin-left:51.75pt;text-indent:-33.75pt;line-height:150%;">a）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">离线计算：跨机房列表中的数据正在传输中（</span>DC1-&gt;DC2<span style="font-family:宋体;">），</span>DC2<span style="font-family:宋体;">上的</span> Job <span style="font-family:宋体;">被暂停调度，等待传输完毕</span> </p>  <p style="margin-left:51.75pt;text-indent:-33.75pt;line-height:150%;">b）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Ad-hoc<span style="font-family:宋体;">查询：</span>DC2<span style="font-family:宋体;">上的</span> Job <span style="font-family:宋体;">需要读</span>DC1<span style="font-family:宋体;">上的数据，</span>Job<span style="font-family:宋体;">暂停调度，通知</span> CrossNode<span style="font-family:宋体;">，数据传输完毕后继续调度</span> </p>  <p style="margin-left:51.75pt;text-indent:-33.75pt;line-height:150%;">c）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman';">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">特殊情况：跨机房数据</span> Join<span style="font-family:宋体;">，</span>DC1<span style="font-family:宋体;">大表，</span>DC2<span style="font-family:宋体;">小表，</span>Job <span style="font-family:宋体;">调度到</span>DC1<span style="font-family:宋体;">上，跨机房直接读取</span>DC2<span style="font-family:宋体;">数据，无需等待</span> </p>  <p style="margin-left:18.0pt;line-height:150%">&nbsp;</p>  <p style="text-indent:18.0pt;line-height:150%"><span style="font-family:宋体;">由于是根据视频和</span>ppt<span style="font-family:宋体;">整理，并没有代码或者文档，所以可能有些地方的理解有偏差，欢迎来提意见</span>~</p></div><img src ="http://www.cppblog.com/whspecial/aggbug/203940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/whspecial/" target="_blank">whspecial</a> 2013-10-27 23:28 <a href="http://www.cppblog.com/whspecial/archive/2013/10/27/203940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dremel存储格式解析</title><link>http://www.cppblog.com/whspecial/archive/2013/08/14/202546.html</link><dc:creator>whspecial</dc:creator><author>whspecial</author><pubDate>Wed, 14 Aug 2013 15:17:00 GMT</pubDate><guid>http://www.cppblog.com/whspecial/archive/2013/08/14/202546.html</guid><wfw:comment>http://www.cppblog.com/whspecial/comments/202546.html</wfw:comment><comments>http://www.cppblog.com/whspecial/archive/2013/08/14/202546.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/whspecial/comments/commentRss/202546.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/whspecial/services/trackbacks/202546.html</trackback:ping><description><![CDATA[<p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp; &nbsp; Dremel是google推出的又一神器，paper中宣称能够在3s内分析1PB的数据，主要是面向交互式查询。这篇paper对嵌套类型的存储方式方面，思维确实有些跳跃，这篇文章主要讲讲这个，一方面是方便后来者理解，另一方面是让自己也整理下思路。<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;首先Dremel使用的是列存模型，对于基本类型列存较容易做到；但是对于嵌套类型，Dremel也能做到将其拆解成基本类型并进行列存，这是值得我们研究的。<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;直观看下嵌套类型按行存储和拆解后按列存储的对比效果：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><a target="_blank" href="http://blog.51cto.com/attachment/201306/230027199.jpg" data_ue_src="http://blog.51cto.com/attachment/201306/230027199.jpg"><img src="http://blog.51cto.com/attachment/201306/230027199.jpg" title="11.jpg" width="450" height="205" border="0" hspace="0" vspace="0" data_ue_src="http://blog.51cto.com/attachment/201306/230027199.jpg" style="width: 450px; height: 205px;"  alt="" /></a></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;然后对于嵌套数据类型，Dremel里面定义了里面三种类型的字段<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;1，必须出现1次而且仅出现1次的字段：required<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;2，可能出现1次或者0次的字段：optional<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;3，可能出现0次或者N次字段：repeated<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;下面以paper的例子来讲述吧：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><a target="_blank" href="http://blog.51cto.com/attachment/201306/225240357.jpg" data_ue_src="http://blog.51cto.com/attachment/201306/225240357.jpg"><img src="http://blog.51cto.com/attachment/201306/225240357.jpg" title="2.jpg" width="450" height="360" border="0" hspace="0" vspace="0" data_ue_src="http://blog.51cto.com/attachment/201306/225240357.jpg" style="width: 450px; height: 360px;"  alt="" /></a></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;其中DocId是required字段，因此在r1,r2中必须出现1次；url字段是optional字段，因此在r1的第三个Name里未出现，在r1的前两个Name里出现了1次；Backward字段是repeated字段，因此在r1的Links里未出现，在r2的Links里出现了2次。<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;理解了上面这些，直接来看下Dremel是怎么来存它的吧：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><a target="_blank" href="http://blog.51cto.com/attachment/201306/231032285.jpg" data_ue_src="http://blog.51cto.com/attachment/201306/231032285.jpg"><img src="http://blog.51cto.com/attachment/201306/231032285.jpg" title="3.jpg" width="450" height="363" border="0" hspace="0" vspace="0" data_ue_src="http://blog.51cto.com/attachment/201306/231032285.jpg" style="width: 450px; height: 363px;"  alt="" /></a></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;上表中的每条记录都有两个属性，"r"代表repetition&nbsp;level，"d"代表definition&nbsp;level，定义如下：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;repetition&nbsp;level:what&nbsp;repeated&nbsp;field&nbsp;in&nbsp;the&nbsp;field&#8217;s&nbsp;path&nbsp;the&nbsp;value&nbsp;has&nbsp;repeated，记录该字段是在哪个repeated级别上重复的</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;definition&nbsp;level:how&nbsp;many&nbsp;fields&nbsp;inpthat&nbsp;could&nbsp;be&nbsp;undefined&nbsp;(because&nbsp;they&nbsp;are&nbsp;optional&nbsp;or&nbsp;repeated)&nbsp;are&nbsp;actually&nbsp;present，记录该字段之上有多少个optional或者repeated字段实际是有值的（本来可以为null的）</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;看到这里，各位可能已经在心里默念了：WTF！别急，可以结合一个例子来看：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><strong>先看repetition&nbsp;level</strong>（下面以r替代），以Name.Language.Code为例：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;1)对第1个出现的值，其r始终为0，因此'en-us'的r为0<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;2)对于第2个值'en'，其上一个值是'en-us'，它们是在Language级别发生的重复，Name.Language是两级的repeated字段，因此r为2<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;3)对于第3个值null，是为了记录'en-gb'是出现在第三个Name而非第二个Name里，特意占位用的。null的上一个值是'en'，它们是在Name级别发生的重复，因此r是1<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;4)对于第4个值'en-gb'，其上一个值是null，它们也是在Name级别发生的重复，因此r是1<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;5)对于第5个值null，其上一个值是'en-gb'，它们出现在两个不同Document里，因此r是0<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;总结下，看repetition&nbsp;level注意两点：1,只比较该值和上一个值；2,只需要看这两个值的重复位置上有几个repeated字段<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><strong>再看definition&nbsp;level</strong>（下面以d替代），也以Name.Language.Code为例：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;1)对于'en-us'，其上的Name，Language都出现了，因此d为2（其实对于非null值的字段，其上的optional或者repeated字段肯定是出现了，所以都是相同的，只是null字段的d值有差别）<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;2)对于'en'，同理d也为2<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;3)对于null，其上只出现了Name，没有出现Language，因此d为1<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;4)对于'en-gb',d也为2<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;5)对于最后一个null，其上也只出现了Name，没有出现Language，因此d为1<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;以上只是讲了dremel怎么去存嵌套类型，至于这种存法是怎么想出来的，真非我辈能理解的了。。。更多内容，请参考原著paper及网上解析。<br /></p><div></div><img src ="http://www.cppblog.com/whspecial/aggbug/202546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/whspecial/" target="_blank">whspecial</a> 2013-08-14 23:17 <a href="http://www.cppblog.com/whspecial/archive/2013/08/14/202546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Orcfile文件格式解析（2）</title><link>http://www.cppblog.com/whspecial/archive/2013/08/14/202545.html</link><dc:creator>whspecial</dc:creator><author>whspecial</author><pubDate>Wed, 14 Aug 2013 15:13:00 GMT</pubDate><guid>http://www.cppblog.com/whspecial/archive/2013/08/14/202545.html</guid><wfw:comment>http://www.cppblog.com/whspecial/comments/202545.html</wfw:comment><comments>http://www.cppblog.com/whspecial/archive/2013/08/14/202545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/whspecial/comments/commentRss/202545.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/whspecial/services/trackbacks/202545.html</trackback:ping><description><![CDATA[<p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp; &nbsp; 上篇文章从整体介绍了Orcfile的存储格式，接下来重点介绍下Orc里用到的几种编码格式：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;字典编码：用于String类型的字段<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Run-Length编码：用于int，long，short等类型的编码</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Bit编码：可以用于各种数据类型<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><strong>1，字典编码：</strong></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;对于String类型的每个字段分别保存一个字典，记录每个值在字典中的位置，保存字典的数据结构采用一棵红黑树。对于每个String字段，最终会有三个输出Stream，分别是StringOuptut(记录字典中的值)，LengthOutput(记录每个字典值的长度)，RowOutput(记录字段在字典中的位置)。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;思考1：为什么要用红黑树？<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;因为红黑树无论是插入，删除，查找的性能都比较平均，都是O(logN)，而且是平衡查找树，最坏情况也不会退化成O(N)<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;思考2：其实一般存储时还会使用LZO之类的压缩，它们本身就是一种字典压缩，为什么Orc里面要自己做字典压缩？<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;因为LZO之类的压缩窗口一般比较小（LZO默认是64KB），而Orc的字典压缩是以整个字段为范围来压缩的，压缩率会更好。<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><strong>2，Run-Length编码：</strong><br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;对于int,long,short类型的字段，使用Run-Length编码。该Run-Length能够对等差数列（完全相等也属于等差数列）进行压缩，该等差数列需要满足以下两个条件：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;1，至少包含3个元素</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;2，差值在-128~127之间（因为差值用1Byte来表示）</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;对于不满足等差数列的数字，Run-Length编码也能存储，但是没有压缩效果，Run-Length的具体存储如下：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;第一个Byte是Control&nbsp;Byte，取值在-128~127之间，其中-1~-128代表后面存储着1~128个不满足等差数列的数字，0~127代表后面存储着3~130个等差数列的数字；</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;如果Control&nbsp;Byte&gt;=0，则后面跟着一个Byte存储差值，否则不存储该Byte；</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;如果Control&nbsp;Byte&gt;=0，则后面跟着等差数列的第一个数，否则跟着-Control&nbsp;Byte个数字。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;例子：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;原始数字：12,12,12,12,12,10,7,13</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;经过Run-Length的数字：<span style="color: #ff0000;">2</span>,<span style="color: #ffc000;">0</span>,12,<span style="color: #ff0000;">-3</span>,10,7,13</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;红色代表Control&nbsp;Byte，黄色代表差值，黑色代表具体的数字。<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><strong>3，Bit编码：</strong></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">对所有类型的字段都可以采用Bit编码来表示该值是否为null。在写任何类型字段之前，先判断该字段值是够为null，如果为null则bit值存为0，否则存为1，对于为null的字段在实际编码时不需要存储了。经过Bit编码之后，可以对于8个bit组成一个Byte，再对其进行Run-Length编码。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;其实除了这三种编码格式之外，Orc对于hive的复杂类型array,map,list等，将其降维成基本类型来存储，这个也是值得借鉴的，如果有空之后会进行分析。</p><img src ="http://www.cppblog.com/whspecial/aggbug/202545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/whspecial/" target="_blank">whspecial</a> 2013-08-14 23:13 <a href="http://www.cppblog.com/whspecial/archive/2013/08/14/202545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Orcfile文件格式解析（1）</title><link>http://www.cppblog.com/whspecial/archive/2013/08/14/202544.html</link><dc:creator>whspecial</dc:creator><author>whspecial</author><pubDate>Wed, 14 Aug 2013 15:12:00 GMT</pubDate><guid>http://www.cppblog.com/whspecial/archive/2013/08/14/202544.html</guid><wfw:comment>http://www.cppblog.com/whspecial/comments/202544.html</wfw:comment><comments>http://www.cppblog.com/whspecial/archive/2013/08/14/202544.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/whspecial/comments/commentRss/202544.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/whspecial/services/trackbacks/202544.html</trackback:ping><description><![CDATA[<p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp; &nbsp; Orcfile(<em>Optimized&nbsp;Row&nbsp;Columnar</em>)是hive&nbsp;0.11版里引入的新的存储格式，是对之前的RCFile存储格式的优化。写这个的哥们来自于HortonWorks，代码写的很不错，比之前的rcfile强多了（据说rcfile是个中科院的童鞋跑去facebook写的，看来中国的计算机教育水平还是有限啊。。。囧，跑题了）</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;先介绍下Orc的文件格式，截一张官方的图：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><a target="_blank" href="http://blog.51cto.com/attachment/201306/234709762.png" data_ue_src="http://blog.51cto.com/attachment/201306/234709762.png"><img src="http://blog.51cto.com/attachment/201306/234709762.png" title="OrcFileLayout.png" data_ue_src="http://blog.51cto.com/attachment/201306/234709762.png"  alt="" /></a></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;可以看到每个Orc文件由1个或多个stripe组成，每个stripe250MB大小，这个Stripe实际相当于之前的rcfile里的RowGroup概念，不过大小由4MB-&gt;250MB，这样应该能提升顺序读的吞吐率。每个Stripe里有三部分组成，分别是Index&nbsp;Data,Row&nbsp;Data,Stripe&nbsp;Footer：</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;1，Index&nbsp;Data：一个轻量级的index，默认是每隔1W行做一个索引。这里做的索引应该只是记录某行的各字段在Row&nbsp;Data中的offset，据说还包括每个Column的max和min值，具体没细看代码。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;2，Row&nbsp;Data：存的是具体的数据，和RCfile一样，先取部分行，然后对这些行按列进行存储。与RCfile不同的地方在于每个列进行了编码，分成多个Stream来存储，具体如何编码在下一篇解析里会讲。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;3，Stripe&nbsp;Footer：存的是各个Stream的类型，长度等信息。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;每个文件有一个File&nbsp;Footer，这里面存的是每个Stripe的行数，每个Column的数据类型信息等；每个文件的尾部是一个PostScript，这里面记录了整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时，会seek到文件尾部读PostScript，从里面解析到File&nbsp;Footer长度，再读FileFooter，从里面解析到各个Stripe信息，再读各个Stripe，即从后往前读。</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;接下来看下ORcfile相对于RCfile做了哪些改进，从Orc作者的ppt里截了张图，分别解释下各行：<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><a target="_blank" href="http://blog.51cto.com/attachment/201306/003840639.png" data_ue_src="http://blog.51cto.com/attachment/201306/003840639.png"><img src="http://blog.51cto.com/attachment/201306/003840639.png" title="图片1.png" width="500" height="345" border="0" hspace="0" vspace="0" data_ue_src="http://blog.51cto.com/attachment/201306/003840639.png" style="width: 500px; height: 345px;"  alt="" /></a></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Hive&nbsp;type&nbsp;model:RCfile在底层存储时不保存类型，都当做Byte流来存储</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Separtor&nbsp;complex&nbsp;columns:Orc将复杂类型拆开存储</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Splits&nbsp;Found&nbsp;Quickly：不很理解<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Default&nbsp;Column&nbsp;group&nbsp;size：不用解释了</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Files&nbsp;per&nbsp;a&nbsp;bucket：不很理解</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Store&nbsp;min，max，count，sum：存了这些便于快速地skip掉一个stripe</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Versioned&nbsp;metadata:不很理解<br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Run-Length&nbsp;Data-coding：整数类型做Run-Length变长编码</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Store&nbsp;Strings&nbsp;in&nbsp;dictionary：String类型做字典编码</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Store&nbsp;Row&nbsp;Count：每个Stripe会存储行数</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Skip&nbsp;Compressed&nbsp;blocks:可以直接skip掉压缩过的block</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;Store&nbsp;internal&nbsp;indexes:存储了一个轻量级的index</p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;"><br /></p><p style="margin-right: 0px; margin-left: 0px; font-family: sans-serif; font-size: 16px; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;整个Orc看下来，代码写的还是比较清晰明了的，而且我们也进行了测试，压缩效果比RCfile提升了不少，有兴趣的朋友可以来看下，之后会写第二篇解析，主要是讲Orc用到的几种编码格式。<br /></p><div></div><img src ="http://www.cppblog.com/whspecial/aggbug/202544.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/whspecial/" target="_blank">whspecial</a> 2013-08-14 23:12 <a href="http://www.cppblog.com/whspecial/archive/2013/08/14/202544.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于map/reduce的combiner运行时机的问题</title><link>http://www.cppblog.com/whspecial/archive/2012/11/06/194819.html</link><dc:creator>whspecial</dc:creator><author>whspecial</author><pubDate>Tue, 06 Nov 2012 15:52:00 GMT</pubDate><guid>http://www.cppblog.com/whspecial/archive/2012/11/06/194819.html</guid><wfw:comment>http://www.cppblog.com/whspecial/comments/194819.html</wfw:comment><comments>http://www.cppblog.com/whspecial/archive/2012/11/06/194819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/whspecial/comments/commentRss/194819.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/whspecial/services/trackbacks/194819.html</trackback:ping><description><![CDATA[<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"></blockquote><span style="font-size: 12pt;">&nbsp; &nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">map/reduce</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">的</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combiner</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">到底在什么时候运行？</span>  <p align="left" style="text-indent: 21pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在网上大多数资料中，都是说</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combiner</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">map</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端运行，发生在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">map</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">输出数据之后，经过</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combiner</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">再传递给</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">reducer</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">。但是之前在工作中出现的一个问题导致我发现原来</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combiner</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">居然也会在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">reducer</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端运行，并且会多次运行。</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;"><br /> </span><span style="font-size: 8pt; line-height: 150%; font-family: Verdana, sans-serif;">&nbsp; &nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在网上查了之后发现，这是</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">hadoop-0.18</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">版本引入的新</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">feature</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">：</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;"><br /> </span><span style="font-size: 8pt; line-height: 150%; font-family: Verdana, sans-serif;">&nbsp; &nbsp;</span><span style="font-size:12.0pt;line-height:150%;font-family:&quot;Arial&quot;,&quot;sans-serif&quot;;color:#333333;background:white;">Changed policy for running combiner. The combiner may be run multiple times as the map's output is sorted and merged. Additionally, it may be run on the reduce side as data is merged. The old semantics are available in Hadoop 0.18 if the user calls:&nbsp;job.setCombineOnlyOnce(true)</span><span style="font-size:12.0pt;line-height:150%;font-family:宋体;color:#333333; background:white;">。</span><span style="font-size: 12pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span><span style="font-size: 8pt; line-height: 150%; font-family: Verdana, sans-serif;">&nbsp; &nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">实际上</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combiner</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">会在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">mapper</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端和</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">reducer</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端分别运运行，看了下代码，发生</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combine</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">的时机在以下：</span><span style="font-size: 8pt; line-height: 150%; font-family: Verdana, sans-serif;"><br /> </span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">&nbsp; &nbsp;1</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">）</span>&nbsp;<span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">mapper</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端的</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">spill</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">阶段，在缓存中的记录超过阈值时会进行</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combine</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">if (spstart != spindex) {</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;</span></p>  <p align="left" style="margin: 2.9pt 0cm; text-indent: 18pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combineAndSpill(kvIter, combineInputCounter);</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">}</span></p>  <p align="left" style="margin: 2.9pt 0cm 2.9pt 18pt; text-indent: -18pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">2</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">）</span>&nbsp;<span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">mapper</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端的</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">merge</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">阶段，进行</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">merge</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">的</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">spill</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">文件数目</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">&gt;=3</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">时会进行</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combine</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">if (null == combinerClass || numSpills &lt; minSpillsForCombine) {</span></p>  <p align="left" style="margin: 2.9pt 0cm; text-indent: 21pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">Merger.writeFile(kvIter, writer, reporter);</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">} else {</span></p>  <p align="left" style="margin: 2.9pt 0cm; text-indent: 21pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combineCollector.setWriter(writer);</span></p>  <p align="left" style="margin: 2.9pt 0cm; text-indent: 21pt; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combineAndSpill(kvIter, combineInputCounter);</span></p>  <p align="left" style="margin: 2.9pt 0cm; line-height: 150%;"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">}</span></p>  <p style="line-height:150%"><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">3</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">）</span>&nbsp;<span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">在</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">reducer</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体;">端，一定会进行</span><span style="font-size: 12pt; line-height: 150%; font-family: Arial, sans-serif;">combine</span></p><span style="font-size: 12pt; font-family: Arial; line-height: 17px; background-color: #ffffff; "><br /></span><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"></blockquote><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"></blockquote><div id="isChromeWebToolbarDiv" style="display:none"></div> <div id="isChromeWebToolbarDiv" style="display:none"></div> <div id="isChromeWebToolbarDiv" style="display:none"></div><img src ="http://www.cppblog.com/whspecial/aggbug/194819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/whspecial/" target="_blank">whspecial</a> 2012-11-06 23:52 <a href="http://www.cppblog.com/whspecial/archive/2012/11/06/194819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>