转载自 ---- http://hi.baidu.com/leexeo/blog/item/cdd173f0979192b7a50f5209.html
前言
MapReduce 在当下绝对是IT技术界的一个热词,在网上,随便搜索一下就能够找到大量关于介绍MapReduce这个programming
model的文章。所以,在本文中,对于MapReduce的原理和模型并不多做介绍,而更侧重于研究一个实现了MapReduce模型的系统的架构。主要的参考文献来自于Google的文献[1],可以在网上找到这篇文章的中文版,不过还是更推荐读原版了。
注:本文中所说的MapReduce模型是指MapReduce的编程模式,而MapReduce系统是指实现了一个MapReduce模型的分布式计算系统。这这里讨论的是Google的MapReduce系统,基于Google
Cluster 这样一个分布式环境。
接口
首先来看一看一个MapReduce系统对外的接口。
Map函数: map(String key, String value)
.....
Reduce函数: reduce(String key, Iterator values) .....
了解MapReduce模型的人应该知道,Map函数的输出是一系列的Key/Value对(pair),这些Key/Value对是给
Reduce函数使用的。但是在这里可以发现,Map函数的输入参数也是Key和Value。但其实,输入的Key/Value和输出的Key
/Value不是同一组东西。对于一个Map函数调用,输入的是一个Key/Value对,而输出呢,是一组Key/Value对。举例来说,如果要统计一篇文章中所有单词的数目,那么输入的Key可能就是行数,输入的Value就是该行的内容。对于一次Map调用,就是要统计出一行中各个单词出现的次数,所以输出的Key是单词,Value是这个单词的出现次数。
Map函数的输入之所以也用Key/Value的形式,可能是因为一般来说一个任务并不是用一次MapReduce就能够完成,而是需要用到多次MapReduce调用,下一个Map调用的输入很有可能就是上一个Reduce的输出结果(Key/Value对)。
系统流程
结合上面的图,这里描述了当一个用户程序执行MapReduce调用后,系统的流程:
1.首先,用户程序中的MapReduce
Library会将输入的文件(就是要处理的文件)切分成大小为16M——64M之间的M份(就是图中的split 0,split
1,...),一般来说,这M份数据是放在了cluster的多台机器上。然后在整个cluster的机器上启动程序的多份拷贝,如图所示,(1)。
2. 其中的一份程序拷贝是master,其余的拷贝是workers。master会将任务分配给workers。任务包括了M个map的任务和R个
reduce的任务,master会找到空闲的worker然后将map或者reduce的任务分配给它。(M的值取决于input
files被切分的块数;R值则是根据map中所能hash出的key的数量。)如图所示,(2)。
3. 当一个worker被分配到map任务,那么它就会处理M份中的一份split。InputData中的数据也是Key/Value形式的很多
pairs(这个在前面中提到了),Map任务的worker会将这些pairs一个一个传递给Map函数,Map函数产生的很多新的Key/Value
对会被缓存在内存中。
4. 周期性的,buffer中缓存的那些pairs会写入到本地disk中。如图所示,(3)(4)。由于有R个reduce任务,所以disk中的pair
会按照一定规则分为R个区,每个区的数据都特定的给某一个reduceWorker。在图中的每个Map Worker所对应的Intermediate
files其实被分成了R个区(很有可能就是R个文件)。这些区的位置会被传递到master上,它会负责将这些位置交给reduce
workers。可以看到,master在这里起到了一个“承上启下”的作用,Map函数和Reduce函数之间的连接是由master完成的。
5. Reduce Worker从master获取了这些区的位置,然后将这些Key/Value对从mapWorker处通过RPC读取。注意,Reduce
Worker只读那些对应于自己的区的数据。如图所示,(5)。读取完数据后需要对于这些Key/Value对按照Key进行排序,如果需要,可能还采取外排的方式(external
sort)。之所以需要排序是因为对于一个Key,会有很多组不同的pair,通过排序可以将它们聚合在一起。
6. reduceWorker迭代整个被排序后的Key/Value数据,将每个独一无二的key和它所对应的value序列(之所以是序列,是因为对于一个
key可能有很多个Key/Value,每个项中的value都不同,它们已经通过排序聚合在了一起)送入Reduce函数中。Reduce函数对于这样的输入产生的结果往往是0或者1个值(比如将所有Value相加,和就是最后的结果)。Reduce函数对于Reduce函数的结果会被添加到最终的
output file里(每次reduce Worker都会产生一个输出文件,最终一共有R个文件,因为一共有R个reduce的任务)。如图所示,(6)。
7. 当所有的map和reduce任务结束后,master会唤醒用户的程序。这时候,用户的MapReduce调用返回。
还需要提及的是,当整个流程顺利完成以后,最终得到的其实是R个文件。如果想要最终的结果,应该将这R个文件合并。但一般来说,都是将这R个文件作为另一个MapReduce任务的输入。
在这里,master起到了三个作用:
1. 它将任务分配给worker;
2. 它维护了所有worker的信息和所处的状态;
3.
它将Map任务结果的位置告诉给Reduce任务,起到了一个桥梁的作用。
容错
Google的这套系统的容错功能在我看来,非常的简单但却实用。举例来说,MapReduce系统通过master来监控其它的
worker,测试它们是否正常。测试的方法非常的简单,就是用ping。master会每隔一段时间就去ping一次worker,如果一定时间内没有返回,那么
master就认为这个机器挂了。
在这里可以和Google Chubby (关于更多Chubby的分析见我上一篇文章
)做一个有意思对比:Chubby中,server与client之间也有类似的监控需求,但是它们是通过一个自定义的握手协议KeepAlive实现的。之所以没有采用ping的方式,是因为这个握手协议不仅仅提供了ping的功能,还传输了其它的一些交互信息。从这里看出,做分布式系统,并没有一定的规则,所有的设计都是根据实际的需求来决定的。
对于一个挂了的机器,根据它上面的任务和这个任务处的状态,分为4类:
1.
Map任务,正在执行。很显然,该Map任务需要被分配到其它worker上重新执行。
2.
Map任务,已经完成。对于这种情况,该Map任务也需要被分配到其它worker上重新执行。原因在于Map任务的结果是存放在本地disk上的,如果机器挂了,那么这些结果自然就访问不了了。
3.
Reduce任务,正在执行。很显然,该任务需要重新执行。
4.
Reduce任务,已经完成。这个情况下,该任务不需要重新执行了。因为Reduce任务的结果是放在了一个公共的分布式文件系统中。机器挂了对于该结果的读取不会有任何的影响。
容错的另一部分,是针对于master。google在这里采取的策略很有意思。如果master挂了,整个MapReduce任务就会被异常中止。用户程序可以捕获到这种异常并决定是否重新执行。也就是说,Google的MapReduce系统对于master的错误并没有“容错”,而是任其发生,将错误处理丢给了用户。
总结
除了上面两节以外,文献[1]中还包括了很多其它的细节和设计,在此就不啰嗦了。
在网上,对于MapReduce这个概念基本上是叫好声一片,毕竟对于很多从来没有做过分布式或者并行计算的人(比如我)来说,MapReduce模型给我们提供了一种崭新的解决问题的思路。但是在这里,我并不想替它唱赞歌(已经有太多人唱了,不差我一个),相反,我觉着另外一些负面的声音可能会更有意思一些。在文章[2]《MapReduce:
A major step
backwards》中,几位数据库方面的大牛对于MapReduce提出了非常严厉的批评,可以说是骂了个狗血淋头。有兴趣的可以看看,很有意思。文章
[3]是它的中文版。
虽然这篇文章的思想我不太苟同,但我也认为不应该将MapReduce过于神化。就连MapReduce的作者也没有回避,MapReduce这个思想其实并不新鲜,很早就在函数式编程中出现了。而且,MapReduce也不是万能灵药,实际上,它只适用于某一类任务,那种可以“分而治之”的任务,MapReduce只是分治思想的一种实现方式。
当然,总的来说MapReduce模型还是成功的。一方面是借了些
google的光,但更重要的,我认为还是在于它的简单。虽然MapReduce可能不是学术界最先进的技术,但是确实迄今为止最实用的一种分布式计算模型,原因就在于它的simple
but effective。我想这多少能对其它的技术有些启示。
分享到:
相关推荐
**Google MapReduce** 是一种分布式计算框架,由Google在2004年提出,用于解决大规模数据处理的问题。它的设计灵感来源于函数式编程中的映射(Map)和化简(Reduce)操作,使得程序员可以方便地编写处理海量数据的...
Google MapReduce(一) MapReduce 是一种解决问题的思路,而不是一个产品,它有多个工程实现,Google 在论文中也给出了它自己的工程架构实现。MapReduce 编程模型解决的问题是能够用分治法解决的问题,如网页抓取...
MapReduce是Google在2004年提出的一种分布式计算模型,用于处理和生成大规模数据集。这个模型简化了大数据处理的复杂性,使得开发者能够编写简单的程序来解决复杂的并行计算问题。它主要由两个阶段组成:Map阶段和...
《Google MapReduce 论文中文版》是一篇详细介绍MapReduce编程模型的重要文献,该模型是Google为处理和生成大规模数据集而设计的一种编程框架。MapReduce的核心思想是将复杂的并行计算任务分解为两个主要阶段:Map和...
在谷歌MapReduce论文中,作者Jeffrey Dean和Sanjay Ghemawat介绍了这一模型的背景、基本概念和实现机制。在此之前,谷歌已经实现了数百个专用计算任务来处理大量的原始数据,例如网页爬取文档、Web请求日志等,进而...
Google MapReduce中文版详细描述了MapReduce编程模型的工作原理和实现细节,同时也介绍了一些实际案例和编程技巧。文档强调了MapReduce在运行时处理的几个关键方面:如何分割输入数据、在计算机集群上调度任务、处理...
Google最早提出这一概念并实现了MapReduce编程模型的框架,用于处理和生成超大数据集。模型的使用者只需要定义Map函数和Reduce函数,而MapReduce框架负责处理数据的分割、任务调度、错误处理以及进程间通信等复杂的...
《Google MapReduce中文版》是关于分布式计算框架MapReduce的一份详细指南,主要针对的是Google开发的这个核心技术。MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行计算,它极大地简化了在大规模集群...
这三篇文章分别详细介绍了谷歌在数据存储、文件系统和大规模并行计算上的创新解决方案。 首先,让我们关注《谷歌Bigtable:一个分布式存储系统》。Bigtable是一种分布式的、可扩展的、高性能的结构化数据存储系统,...
Google MapReduce中文版Google MapReduce中文版Google MapReduce中文版Google MapReduce中文版Google MapReduce中文版Google MapReduce中文版
它由Google提出并广泛应用于大数据处理领域。MapReduce的核心思想是将复杂的大规模数据处理任务分解成两个阶段:Map阶段和Reduce阶段。 - **Map阶段**:在这个阶段,用户定义一个map函数,该函数负责处理输入的键值...
论文《MapReduce: Simplified Data Processing on Large Clusters》(mapreduce-osdi04.pdf)深入介绍了这一概念。 **2. GFS(Google File System)** GFS是Google设计的一个分布式文件系统,旨在处理PB级别的数据...
### Google MapReduce中文版:深度解析与应用 #### 引言 Google MapReduce是一个革命性的编程模型和算法框架,旨在处理和生成超大数据集。它不仅简化了大规模数据处理的复杂性,还允许非专业程序员有效地利用分布式...
MapReduce 是一种由 Google 提出的编程模型,用于处理和生成大规模数据集。它源于实际需求,即如何在大量普通计算机上并行处理海量数据。MapReduce 的核心思想是将复杂的数据处理任务分解为两个主要阶段:Map 和 ...
谷歌在03到06年间连续发表了三篇很有影响力的文章,分别是03年SOSP的GFS,04年OSDI的MapReduce,和06年OSDI的BigTable。SOSP和OSDI都是操作系统领域的顶级会议,在计算机学会推荐会议里属于A类。SOSP在单数年举办,...
这些技术包括MapReduce、GFS(Google File System)和Bigtable,它们对现代大数据处理和云计算的发展产生了深远影响。以下是这三项技术的详细介绍: 1. MapReduce: MapReduce是一种编程模型,用于大规模数据集的...
在MapReduce问世之前,Google的工程师们,包括其发明者Jeffrey Dean和Sanjay Ghemawat,面临着一个共同的挑战:如何高效地处理海量原始数据。这些数据可能来自网页抓取文档、网络请求日志等,目标是计算各种派生数据...
google-mapreduce中文版