Hadoop 提供了一个稳定的共享存储和分析系统。存储由HDFS 实现,分析由MapReduce 实现。纵然Hadoop 还有其他功能,但这些功能是它的核心所在。
相较于其他系统
MapReduce 似乎采用的是一种蛮力方法。即,针对每个查询,每一个数据集-- 至少是很大一部分-- 都会被处理。但这正是它的能力。MapReduce 可以处理一批查询,并且它针对整个数据集处理即席查询并在合理时间内获得结果的能力也是具有突破性的。它改变了我们对数据的看法,并且解放了以前存储在磁带和磁盘上的数据。它赋予我们对数据进行创新的机会。那些以前需要很长时间才能获得答案的问题现在已经迎刃而解。
1. 关系型数据库管理系统
为什么我们不能使用数据库加上更多磁盘来做大规模的批量分析?为什么我们需要MapReduce?
这个问题的答案来自于磁盘驱动器的另一个发展趋势:寻址时间的提高速度远远慢于传输速率的提高速度。寻址就是将磁头移动到特定位置进行读写操作的工序。它的特点是磁盘操作有延迟,而传输速率对应于磁盘的带宽。如果数据的访问模式受限于磁盘的寻址,势必会导致它花更长时间(相较于流)来读或写大部分数据。另一方面,在更新一小部分数据库记录的时候,传统的B 树(关系型数据库中使用的一种数据结构,受限于执行查找的速度)效果很好。但在更新大部分数据库数据的时候,B 树的效率就没有MapReduce 的效率高,因为它需要使用排序/合并来重建数据库。
在许多情况下,MapReduce 能够被视为一种RDBMS(关系型数据库管理系统)的补充。(两个系统之间的差异见表1-1)。MapReduce 很适合处理那些需要分析整个数据集的问题,以批处理的方式,尤其是Ad Hoc(自主或即席)分析。RDBMS 适用于点查询和更新(其中,数据集已经被索引以提供低延迟的检索和短时间的少量数据更新)。MapReduce 适合数据被一次写入和多次读取的应用,而关系型数据库更适合持续更新的数据集。
MapReduce 和关系型数据库之间的另一个区别是它们操作的数据集中的结构化数据的数量。结构化数据是拥有准确定义的实体化数据,具有诸如XML 文档或数据库表定义的格式,符合特定的预定义模式。这就是RDBMS 包括的内容。另一方面,半结构化数据比较宽松,虽然可能有模式,但经常被忽略,所以它只能用作数据结构指南。例如,一张电子表格,其中的结构便是单元格组成的网格,尽管其本身可能保存任何形式的数据。非结构化数据没有什么特别的内部结构,例如纯文本或图像数据。MapReduce 对于非结构化或半结构化数据非常有效,因为它被设计为在处理时间内解释数据。换句话说:MapReduce 输入的键和值并不是数据固有的属性,它们是由分析数据的人来选择的。
关系型数据往往是规范的,以保持其完整性和删除冗余。规范化为MapReduce 带来问题,因为它使读取记录成为一个非本地操作(即需要从其他主机上拷贝自己需要的数据),并且MapReduce 的核心假设之一就是,它可以进行(高速)流的读写。Web 服务器日志是记录集的一个很好的非规范化例子(例如,客户端主机名每次都以全名来指定,即使同一客户端可能会出现很多次),这也是MapReduce 非常适合用于分析各种日志文件的原因之一。
MapReduce 是一种线性的可伸缩的编程模型。程序员编写两个函数-- map 函数和Reduce 函数-- 每一个都定义一个键/值对集映射到另一个。这些函数无视数据的大小或者它们正在使用的集群的特性,这样它们就可以原封不动地应用到小规模数据集或者大的数据集上。更重要的是,如果放入两倍的数据量,运行的时间会少于两倍。但是如果是两倍大小的集群,一个任务任然只是和原来的一样快。这不是一般的SQL 查询的效果。
随着时间的推移,关系型数据库和MapReduce 之间的差异很可能变得模糊。关系型数据库都开始吸收MapReduce 的一些思路(如ASTER DATA 的和GreenPlum 的数据库),另一方面,基于MapReduce 的高级查询语言(如Pig 和Hive)使MapReduce 的系统更接近传统的数据库编程人员。
2. 网格计算
高性能计算(High Performance Computing,HPC)和网格计算社区多年来一直在做大规模的数据处理,它们使用的是消息传递接口(Message Passing Interface,MPI)这样的API。从广义上讲,高性能计算的方法是将作业分配给一个机器集群,这些机器访问共享文件系统,由一个存储区域网络(Storage Area Network,SAN)进行管理。这非常适用于以主计算密集型为主的作业,但当节点需要访问的大数据量(数百GB 的数据,这是MapReduce 实际开始"发光"的起点)时,这会成为一个问题,因为网络带宽成为"瓶颈",所以计算节点闲置下来了。
MapReduce 尝试在计算节点本地存储数据,因此数据访问速度会因为它是本地数据而比较快。 这项"数据本地化"功能,成为MapReduce 的核心功能并且也是它拥有良好性能的原因之一。意识到网络带宽在数据中心环境是最有价值的资源(到处复制数据会很容易的把网络带宽饱和)之后,MapReduce 便通过显式网络拓扑结构不遗余力地加以保护。请注意,这种安排不会排除MapReduce 中的高CPU 使用分析。
MPI 赋予程序员很大的控制,但也要求显式控制数据流机制,需要使用传统的C 语言的功能模块完成(例如socket),以及更高级的算法来进行分析。而MapReduce 却是在更高层面上完成任务,即程序员从键/值对函数的角度来考虑,同时数据流是隐含的。
在一个大规模分布式计算平台上协调进程是一个很大的挑战。最困难的部分是恰当的处理失效与错误-- 在不知道一个远程进程是否已经失败的时候-- 仍然需要继续整个计算。MapReduce 将程序员从必须考虑失败任务的情况中解放出来,它检测失败的map 或者reduce任务,在健康的机器上重新安排任务。MapReduce 能够做到这一点,因为它是一个无共享的架构,这意味着各个任务之间彼此并不依赖。(这里讲得稍微简单了一些,因为mapper 的输出是反馈给reducer 的,但这由MapReduce 系统控制。在这种情况下,相对于返回失败的map,应该对返回reducer 给予更多关注,因为它必须确保它可以检索到必要的map 输出,如果不行,必须重新运行相关的map 从而生成必要的这些输出。)因此,从程序员的角度来看,执行任务的顺序是无关紧要的。相比之下,MPI 程序必须显式地管理自己的检查点和恢复机制,从而把更多控制权交给程序员,但这样会加大编程的难度。
MapReduce 听起来似乎是一个相当严格的编程模型,而且在某种意义上看的确如此:我们被限定于键/值对的类型(它们按照指定的方式关联在一起),mapper 和reducer 彼此间的协作有限,一个接一个地运行(mapper 传输键/值对给reducer)。对此,一个很自然的问题是:你是否能用它做点儿有用或普通的事情?
答案是肯定的。MapReduce 作为一个建立搜索索引产品系统,是由Google 的工程师们开发出来的,因为他们发现自己一遍又一遍地解决相同的问题(MapReduce 的灵感来自传统的函数式编程、分布式计算和数据库社区),但它后来被应用于其他行业的其他许多应用。我们惊喜地看到许多算法的变体在MapReduce 中得以表示,从图像图形分析,到基于图表的问题,再到机器学习算法 。它当然不能解决所有问题,但它是一个很普遍的数据处理工具。
3. 志愿计算
人们第一次听说Hadoop 和MapReduce 的时候,经常会问:"和SETI@home 有什么区别?"SETI,全称为Search for Extra-Terrestrial Intelligence(搜寻外星人),运行着一个称为SETI@home 的项目(http://setiathome.berkeley.edu)。在此项目中,志愿者把自己计算机CPU的空闲时间贡献出来分析无线天文望远镜的数据借此寻外星智慧生命信号。SETI@home 是最有名的拥有许多志愿者的项目,其他的还有Great Internet Mersenne Prime Search(搜索大素数)与Folding@home 项目(了解蛋白质构成及其与疾病之间的关系)。志愿计算项目通过将他们试图解决的问题分为几个他们成为工作单元的块来工作,并将它们送到世界各地的电脑上进行分析。例如,SETI@home 的工作单元大约是0.35 MB 的无线电望远镜数据,并且一个典型的计算机需要数小时或数天来分析。完成分析后,结果发送回服务器,客户端获得的另一项工作单元。作为防止欺骗的预防措施,每个工作单元必须送到三台机器上并且需要有至少两个结果相同才会被接受。虽然SETI@home 在表面上可能类似于MapReduce(将问题分为独立的块,然后进行并行计算),但差异还是显著的。SETI@home 问题是CPU 高度密集型的,使其适合运行于世界各地成千上万台计算机上,因为相对于其计算时间而言,传输工作单元的时间微不足道 。志愿者捐献的是CPU 周期,而不是带宽。
MapReduce 被设计为用来运行那些需要数分钟或数小时的作业,这些作业在一个聚集带宽很高的数据中心中可信任的专用硬件设备上运行。相比之下,SETI@home 项目是在接入互联网的不可信的计算机上运行,这些计算机的网速不同,而且数据也不在本地。