标签:style blog http io os 使用 ar java for
江湖传说永流传:谷歌技术有"三宝",GFS、MapReduce和大表(BigTable)!
谷歌在03到06年间连续发表了三篇非常有影响力的文章,各自是03年SOSP的GFS,04年OSDI的MapReduce,和06年OSDI的BigTable。SOSP和OSDI都是操作系统领域的顶级会议,在计算机学会推荐会议里属于A类。SOSP在单数年举办,而OSDI在双数年举办。
那么这篇博客就来介绍一下MapReduce。
GFS和BigTable已经为我们提供了高性能、高并发的服务,可是并行编程可不是全部程序猿都玩得转的活儿,假设我们的应用本身不能并发,那GFS、BigTable也都是没有意义的。MapReduce的伟大之处就在于让不熟悉并行编程的程序猿也能充分发挥分布式系统的威力。
简单概括的说,MapReduce是将一个大作业拆分为多个小作业的框架(大作业和小作业应该本质是一样的,仅仅是规模不同),用户须要做的就是决定拆成多少份,以及定义作业本身。
以下用一个贯穿全文的样例来解释MapReduce是怎样工作的。
假设我想统计下过去10年计算机论文出现最多的几个单词,看看大家都在研究些什么,那我收集好论文后,该怎么办呢?
方法一:我能够写一个小程序,把全部论文按顺序遍历一遍,统计每个遇到的单词的出现次数,最后就能够知道哪几个单词最热门了。
这样的方法在数据集比較小时,是非常有效的,并且实现最简单,用来解决问题非常合适。
方法二:写一个多线程程序,并发遍历论文。
这个问题理论上是能够高度并发的,由于统计一个文件时不会影响统计还有一个文件。当我们的机器是多核或者多处理器,方法二肯定例如法一高效。可是写一个多线程程序要例如法一困难多了,我们必须自己同步共享数据,例如要防止两个线程反复统计文件。
方法三:把作业交给多个计算机去完毕。
我们能够用法一的程序,部署到N台机器上去,然后把论文集分成N份,一台机器跑一个作业。这种方法跑得足够快,可是部署起来非常麻烦,我们要人工把程序copy到别的机器,要人工把论文集分开,最痛苦的是还要把N个执行结果进行整合(当然我们也能够再写一个程序)。
方法四:让MapReduce来帮帮我们吧!
MapReduce本质上就是方法三,可是怎样拆分文件集,怎样copy程序,怎样整合结果这些都是框架定义好的。我们仅仅要定义好这个任务(用户程序),其他都交给MapReduce。
在介绍MapReduce怎样工作之前,先讲讲两个核心函数map和reduce以及MapReduce的伪代码。
map函数和reduce函数是交给用户实现的,这两个函数定义了任务本身。
统计词频的MapReduce函数的核心代码很简短,主要就是实现这两个函数。
map(String key, String value): // key: document name // value: document contents for each word w in value: EmitIntermediate(w, "1"); reduce(String key, Iterator values): // key: a word // values: a list of counts int result = 0; for each v in values: result += ParseInt(v); Emit(AsString(result));在统计词频的样例里,map函数接受的键是文件名称,值是文件的内容,map逐个遍历单词,每遇到一个单词w,就产生一个中间键值对<w, "1">,这表示单词w咱又找到了一个;MapReduce将键同样(都是单词w)的键值对传给reduce函数,这样reduce函数接受的键就是单词w,值是一串"1"(最主要的实现是这样,但能够优化),个数等于键为w的键值对的个数,然后将这些“1”累加就得到单词w的出现次数。最后这些单词的出现次数会被写到用户定义的位置,存储在底层的分布式存储系统(GFS或HDFS)。
上图是论文里给出的流程图。一切都是从最上方的user program開始的,user program链接了MapReduce库,实现了最主要的Map函数和Reduce函数。图中运行的顺序都用数字标记了。
全部运行完成后,MapReduce输出放在了R个分区的输出文件里(分别相应一个Reduce作业)。用户通常并不须要合并这R个文件,而是将其作为输入交给还有一个MapReduce程序处理。整个过程中,输入数据是来自底层分布式文件系统(GFS)的,中间数据是放在本地文件系统的,终于输出数据是写入底层分布式文件系统(GFS)的。并且我们要注意Map/Reduce作业和map/reduce函数的差别:Map作业处理一个输入数据的分片,可能须要调用多次map函数来处理每一个输入键值对;Reduce作业处理一个分区的中间键值对,期间要对每一个不同的键调用一次reduce函数,Reduce作业终于也相应一个输出文件。
我更喜欢把流程分为三个阶段。第一阶段是准备阶段,包含1、2,主角是MapReduce库,完毕拆分作业和拷贝用户程序等任务;第二阶段是执行阶段,包含3、4、5、6,主角是用户定义的map和reduce函数,每一个小作业都独立执行着;第三阶段是扫尾阶段,这时作业已经完毕,作业结果被放在输出文件中,就看用户想怎么处理这些输出了。
结合第四节,我们就能够知道第三节的代码是怎样工作的了。如果咱们定义M=5,R=3,而且有6台机器,一台master。
这幅图描写叙述了MapReduce怎样处理词频统计。因为map worker数量不够,首先处理了分片1、3、4,并产生中间键值对;当全部中间值都准备好了,Reduce作业就開始读取相应分区,并输出统计结果。
标签:style blog http io os 使用 ar java for
原文地址:http://www.cnblogs.com/mengfanrong/p/4015535.html