网格计算
高性能计算(High Performance Computing,HPC)和网格计算(Grid Computing)组织多年来一直在研究大规模数据处理,主要使用类似于消息传递接口(Message Passing Interface,MPI)的API。从广义上讲,高性能计算的方法是将作业分散到集群的各台机器上,这些机器访问由存储区域网络(SAN)组织的共享文件系统。这比较适用于计算密集型的作业,但如果节点需要访问更大量的数据(几百个GB的数据,这时MapReduce开始发挥其优势),那么很多计算节点会由于网络带宽的瓶颈问题而空闲下来等待数据。
MapReduc会尽量在计算节点上存储数据,以实现数据的本地快速访问。[1]数据本地化(data locality)特性是MapReduce的核心特征,并因此而获得良好的性能。意识到网络带宽是数据中心环境最珍贵的资源(到处复制数据很容易耗尽网络带宽) 之后,MapReduce通过显式网络拓扑结构尽力保留网络带宽。注意,这种排列方式并未降低MapReduce的计算密集型的数据分析能力。
MPI赋予了程序员极大的控制能力,但是需要程序员显式控制数据流机制,包括通过C语言构造低层次的功能模块(例如套接字)和高层次的数据分析算法。而MapReduce则在更高层次上执行任务,即程序员仅从键/值对函数的角度考虑任务的执行,这样数据流是隐含的。
在大规模分布式计算环境下,协调各进程间的执行是一个很大的挑战。最困难的是合理地处理系统部分失效问题——在不知道一个远程进程是否已失效的情况下——同时还需要继续完成整个计算。MapReduce 让程序员无需考虑系统的部分失效问题,因为自身的系统实现能够检测到失败的map或reduce任务,并让正常运行的机器重新执行这些失败的任务。正是由于采用了无共享(shared-nothing)框架,所以MapReduce才能够实现失败检测,这意味着各个任务之间彼此独立。(这里讲得过于简单了一点,因为MapReduce 系统本身控制着mapper的输出结果传给reducer的过程;这种情况下,重新运行 reducer比重新运行mapper更需要格外小心,因为reducer需要获取必要的mapper 的输出结果,如果没有获得必要的输出结果,必须再次运行相关mapper重新生成输出结果。) 因此,从程序员的角度来看,任务的执行顺序是无关紧要的。相比之下,MPI 程序必须显式地管理自身的检查点和恢复机制,尽管更多的控制权交给了程序员,但也加大了编程的难度。
MapReduce听起来似乎是一个相当严格的编程模型,而且在某种意义上看,它的确如此:用户被限定于使用具有特定关联的键/值对,mapper和reducer彼此间可做的协调非常有限(每个mapper将键/值对传给reducer)。由此自然会联想到一个问题:能用该编程模型做一些有用或不普通的事情吗?
答案是肯定的。MapReduce是由谷歌的工程师开发的,用于构建搜索引擎的索引,并且他们证明了它能够一次又一次地解决这一索引问题。MapReduce 的灵感来自于传统的函数式编程、分布式计算和数据库社区,此后该模型在其他行业有着很多其他的应用。我们惊喜地发现,有许多算法可以使用 MapReduce来表达,从
图像图形分析到各类基于图像分析的问题,再到机器学习算法。[2]当然,它不能解决所有问题,但它确实是一个比较通用的数据处理工具。
我们将在第16章介绍Hadoop的一些典型应用。
[1] Jim Gray首先支持在存储数据附近的机器上进行计算。参见“Distributed Computing
Economics”(March 2003), 网址为http://research.microsoft.com/apps/pubs/default.aspx? id=70001。
[2] Apache Mahout(http://mahout.apache.org/)是一个在Hadoop上运行的机器学习类库(例如分类和聚类算法)。