本节我们用在一个大型集群上运行的两个计算来衡量MapReduce的性能。一个计算在大约1TB的数据中 进行特定的模式匹配,另一个计算对大约1TB的数据进行排序。
这两个程序在大量的使用MapReduce的实际应用中是非常典型的 — 一类是对数据格式进行转换,从一种 表现形式转换为另外一种表现形式;另一类是从海量数据中抽取少部分的用户感兴趣的数据。
5.1、集群配置
所有这些程序都运行在一个大约由1800台机器构成的集群上。每台机器配置2个2G主频、支持超线程的 Intel Xeon处理器,4GB的物理内存,两个160GB的IDE硬盘和一个千兆以太网卡。这些机器部署在一个 两层的树形交换网络中,在root节点大概有100-200GBPS的传输带宽。所有这些机器都采用相同的部署
(对等部署),因此任意两点之间的网络来回时间小于1毫秒。
在4GB内存里,大概有1-1.5G用于运行在集群上的其他任务。测试程序在周末下午开始执行,这时主机的 CPU、磁盘和网络基本上处于空闲状态。
5.2、GREP
这个分布式的grep程序需要扫描大概10的10次方个由100个字节组成的记录,查找出现概率较小的3个 字符的模式(这个模式在92337个记录中出现)。输入数据被拆分成大约64M的Block(M=15000),
整个输出数据存放在一个文件中(R=1)。
图2显示了这个运算随时间的处理过程。其中Y轴表示输入数据的处理速度。处理速度随着参与
MapReduce计算的机器数量的增加而增加,当1764台worker参与计算的时,处理速度达到了30GB/s。
当Map任务结束的时候,即在计算开始后80秒,输入的处理速度降到0。整个计算过程从开始到结束一共 花了大概150秒。这包括了大约一分钟的初始启动阶段。初始启动阶段消耗的时间包括了是把这个程序传 送到各个worker机器上的时间、等待GFS文件系统打开1000个输入文件集合的时间、获取相关的文件本 地位置优化信息的时间。
5.3、排序
排序程序处理10的10次方个100个字节组成的记录(大概1TB的数据)。这个程序模仿TeraSort benchmark[10]。
排序程序由不到50行代码组成。只有三行的Map函数从文本行中解析出10个字节的key值作为排序的 key,并且把这个key和原始文本行作为中间的key/value pair值输出。我们使用了一个内置的恒等函数作 为Reduce操作函数。这个函数把中间的key/value pair值不作任何改变输出。最终排序结果输出到两路 复制的GFS文件系统(也就是说,程序输出2TB的数据)。
如前所述,输入数据被分成64MB的Block(M=15000)。我们把排序后的输出结果分区后存储到4000 个文件(R=4000)。分区函数使用key的原始字节来把数据分区到R个片段中。
在这个benchmark测试中,我们使用的分区函数知道key的分区情况。通常对于排序程序来说,我们会增 加一个预处理的MapReduce操作用于采样key值的分布情况,通过采样的数据来计算对最终排序处理的分 区点。
图三(a)显示了这个排序程序的正常执行过程。左上的图显示了输入数据读取的速度。数据读取速度峰值 会达到13GB/s,并且所有Map任务完成之后,即大约200秒之后迅速滑落到0。值得注意的是,排序程序 输入数据读取速度小于分布式grep程序。这是因为排序程序的Map任务花了大约一半的处理时间和I/O带 宽把中间输出结果写到本地硬盘。相应的分布式grep程序的中间结果输出几乎可以忽略不计。
左边中间的图显示了中间数据从Map任务发送到Reduce任务的网络速度。这个过程从第一个Map任务完 成之后就开始缓慢启动了。图示的第一个高峰是启动了第一批大概1700个Reduce任务(整个
MapReduce分布到大概1700台机器上,每台机器1次最多执行1个Reduce任务)。排序程序运行大约 300秒后,第一批启动的Reduce任务有些完成了,我们开始执行剩下的Reduce任务。所有的处理在大约 600秒后结束。
左下图表示Reduce任务把排序后的数据写到最终的输出文件的速度。在第一个排序阶段结束和数据开始 写入磁盘之间有一个小的延时,这是因为worker机器正在忙于排序中间数据。磁盘写入速度在2-4GB/s持 续一段时间。输出数据写入磁盘大约持续850秒。计入初始启动部分的时间,整个运算消耗了891秒。这 个速度和TeraSort benchmark[18]的最高纪录1057秒相差不多。
还有一些值得注意的现象:输入数据的读取速度比排序速度和输出数据写入磁盘速度要高不少,这是因为 我们的输入数据本地化优化策略起了作用 — 绝大部分数据都是从本地硬盘读取的,从而节省了网络带 宽。排序速度比输出数据写入到磁盘的速度快,这是因为输出数据写了两份(我们使用了2路的GFS文件 系统,写入复制节点的原因是为了保证数据可靠性和可用性)。我们把输出数据写入到两个复制节点的原 因是因为这是底层文件系统的保证数据可靠性和可用性的实现机制。如果底层文件系统使用类似容错编码 [14](erasure coding)的方式而不是复制的方式保证数据的可靠性和可用性,那么在输出数据写入磁盘的 时候,就可以降低网络带宽的使用。
5.4、高效的backup任务
图三(b)显示了关闭了备用任务后排序程序执行情况。执行的过程和图3(a)很相似,除了输出数据写 磁盘的动作在时间上拖了一个很长的尾巴,而且在这段时间里,几乎没有什么写入动作。在960秒后,只 有5个Reduce任务没有完成。这些拖后腿的任务又执行了300秒才完成。整个计算消耗了1283秒,多了 44%的执行时间。
5.5、失效的机器
在图三(c)中演示的排序程序执行的过程中,我们在程序开始后几分钟有意的kill了1746个worker中的 200个。集群底层的调度立刻在这些机器上重新开始新的worker处理进程(因为只是worker机器上的处 理进程被kill了,机器本身还在工作)。
图三(c)显示出了一个“负”的输入数据读取速度,这是因为一些已经完成的Map任务丢失了(由于相应 的执行Map任务的worker进程被kill了),需要重新执行这些任务。相关Map任务很快就被重新执行了。
整个运算在933秒内完成,包括了初始启动时间(只比正常执行多消耗了5%的时间)。
6、经验
我们在2003年1月完成了第一个版本的MapReduce库,在2003年8月的版本有了显著的增强,这包括了 输入数据本地优化、worker机器之间的动态负载均衡等等。从那以后,我们惊喜的发现,MapReduce库 能广泛应用于我们日常工作中遇到的各类问题。它现在在Google内部各个领域得到广泛应用,包括:
大规模机器学习问题
Google News和Froogle产品的集群问题
从公众查询产品(比如Google的Zeitgeist)的报告中抽取数据。
从大量的新应用和新产品的网页中提取有用信息(比如,从大量的位置搜索网页中抽取地理位置信 息)。
大规模的图形计算。
图四显示了在我们的源代码管理系统中,随着时间推移,独立的MapReduce程序数量的显著增加。从 2003年早些时候的0个增长到2004年9月份的差不多900个不同的程序。MapReduce的成功取决于采用 MapReduce库能够在不到半个小时时间内写出一个简单的程序,这个简单的程序能够在上千台机器的组 成的集群上做大规模并发处理,这极大的加快了开发和原形设计的周期。另外,采用MapReduce库,可 以让完全没有分布式和/或并行系统开发经验的程序员很容易的利用大量的资源,开发出分布式和/或并行 处理的应用。
在每个任务结束的时候,MapReduce库统计计算资源的使用状况。在表1,我们列出了2004年8月份 MapReduce运行的任务所占用的相关资源。
6.1、大规模索引
到目前为止,MapReduce最成功的应用就是重写了Google网络搜索服务所使用到的index系统。索引系 统的输入数据是网络爬虫抓取回来的海量的文档,这些文档数据都保存在GFS文件系统里。这些文档原始 内容(alex注:raw contents,我认为就是网页中的剔除html标记后的内容、pdf和word等有格式文档 中提取的文本内容等)的大小超过了20TB。索引程序是通过一系列的MapReduce操作(大约5到10次)
来建立索引。使用MapReduce(替换上一个特别设计的、分布式处理的索引程序)带来这些好处:
实现索引部分的代码简单、小巧、容易理解,因为对于容错、分布式以及并行计算的处理都是 MapReduce库提供的。比如,使用MapReduce库,计算的代码行数从原来的3800行C++代码减 少到大概700行代码。
MapReduce库的性能已经足够好了,因此我们可以把在概念上不相关的计算步骤分开处理,而不是 混在一起以期减少数据传递的额外消耗。概念上不相关的计算步骤的隔离也使得我们可以很容易改变 索引处理方式。比如,对之前的索引系统的一个小更改可能要耗费好几个月的时间,但是在使用 MapReduce的新系统上,这样的更改只需要花几天时间就可以了。
索引系统的操作管理更容易了。因为由机器失效、机器处理速度缓慢、以及网络的瞬间阻塞等引起的 绝大部分问题都已经由MapReduce库解决了,不再需要操作人员的介入了。另外,我们可以通过在 索引系统集群中增加机器的简单方法提高整体处理性能。
7、相关工作
很多系统都提供了严格的编程模式,并且通过对编程的严格限制来实现并行计算。例如,一个结合函数可 以通过把N个元素的数组的前缀在N个处理器上使用并行前缀算法,在log N的时间内计算完[6,9,13]
(alex注:完全没有明白作者在说啥,具体参考相关6、9、13文档)。MapReduce可以看作是我们结合 在真实环境下处理海量数据的经验,对这些经典模型进行简化和萃取的成果。更加值得骄傲的是,我们还
(alex注:完全没有明白作者在说啥,具体参考相关6、9、13文档)。MapReduce可以看作是我们结合 在真实环境下处理海量数据的经验,对这些经典模型进行简化和萃取的成果。更加值得骄傲的是,我们还