现在MapReduce/Hadoop以及相关的数据处理技术非常热,因此我想在这里将MapReduce的优势汇总一下,将MapReduce与传统基于HPC集群的并行计算模型做一个简要比较,也算是对前一阵子所学的MapReduce知识做一个总结和梳理。
引言
随着互联网数据量的不断增长,对处理数据能力的要求也变得越来越高。当计算量超出单机的处理能力极限时,采取并行计算是一种自然而然的解决之道。在MapReduce出现之前,已经有像MPI这样非常成熟的并行计算框架了,那么为什么Google还需要MapReduce,MapReduce相较于传统的并行计算框架有什么优势,这是本文关注的问题。
文章之初先给出一个传统并行计算框架与MapReduce的对比表格,然后一项项对其进行剖析。
传统 | MapReduce | |
集群架构/容错性 | 共享式(共享内存/共享存储),容错性差 | 无共享式,容错性好 |
硬件/价格/扩展性 | 刀片服务器、高速网、SAN,价格贵,扩展性差 | 普通PC机(便宜),便宜,扩展性好 |
编程/学习难度 | what+how,难 | what,简单 |
适用场景 | 实时、细粒度计算、计算密集型 | 批处理、非实时、数据密集型 |
集群架构/容错性
在传统的并行计算中,计算资源通常展示为一台逻辑上统一的计算机。对于一个由多个刀片、SAN构成的HPC集群来说,展现给程序员的仍旧是一台计算机,只不过这台计算拥有为数众多的CPU,以及容量巨大的主存与磁盘。在物理上,计算资源与存储资源是两个相对分离的部分,数据从数据节点通过数据总线或者高速网络传输到达计算节点。对于数据量较小的计算密集型处理,这并不是问题。而对于数据密集型处理,计算节点与存储节点之间的I/O将成为整个系统的性能瓶颈。共享式架构造成数据集中放置,从而造成I/O传输瓶颈。此外,由于集群组件间耦合、依赖较紧密,集群容错性较差。
而实际上,当数据规模大的时候,数据会体现出一定的局部性特征,因此将数据统一存放、统一读出的做法并不是最佳的。MapReduce致力于解决大规模数据处理的问题,因此在设计之初就考虑了数据的局部性原理,利用局部性原理将整个问题分而治之。MapReduce集群由普通PC机构成,为无共享式架构。在处理之前,将数据集分布至各个节点。处理时,每个节点就近读取本地存储的数据处理(map),将处理后的数据进行合并(combine)、排序(shuffle and sort)后再分发(至reduce节点),避免了大量数据的传输,提高了处理效率。无共享式架构的另一个好处是配合复制(replication)策略,集群可以具有良好的容错性,一部分节点的down机对集群的正常工作不会造成影响。
硬件/价格/扩展性
传统的HPC集群由高级硬件构成,十分昂贵,若想提高HPC集群的性能,通常采取纵向扩展的方式:即换用更快的CPU、增加刀片、增加内存、扩展磁盘等。但这种扩展方式不能支撑长期的计算扩展(很容易就到顶了)且升级费用昂贵。因此相对于MapReduce集群,HPC集群的扩展性较差。
MapReduce集群由普通PC机构成,普通PC机拥有更高的性价比,因此同等计算能力的集群,MapReduce集群的价格要低得多。不仅如此,MapReduce集群中的节点通过以太网进行连接,因而具有良好的横向扩展性,即可以通过添加PC机节点的方式提高处理能力。Yahoo!拥有世界上最大的Hadoop集群,包含4000多个节点(Google的MapReduce集群规模应该更大,但好像没公布过具体数字,如有网友知情,还望不吝赐教)。
编程/学习难度
传统的并行计算模型都有着与多线程模型类似的逻辑,这种编程模型最大的问题是程序的行为难以控制。为了保证正确的执行结果,需要小心控制共享资源的访问,并由此发展出了互斥量、信号量、锁等一系列同步技术,也带来了诸如争抢、饥饿、死锁等问题。程序员在使用传统并行计算模型编程时,不仅仅要考虑要做的事情(即“what to do”:使用并行模型描述需要解决的问题),还要考虑程序执行的细节(即“how to do”,程序执行中的诸多同步、通信问题),这使得并行编程十分困难。已有的编程模型,例如MPI、OpenCL、CUDA也只是在较低的层次做了封装,需要处理的程序执行细节依然很多。
MapReduce则做了更多处理:MapReduce不仅包含编程模型,还提供一个运行时环境,用以执行MapReduce程序,并行程序执行的诸多细节,如分发、合并、同步、监测等功能均交由执行框架负责。使用MapReduce,程序员只需要考虑如何使用MapReduce模型描述问题(what),而无需操心程序是如何执行的(how),这使得MapReduce易学易用。
适用场景
说了这么多MapReduce的好话,MapReduce是万金油吗?
答案是否定的,无论什么时候,都不应该忘记MapReduce的设计初衷:解决大规模、非实时数据处理问题。大规模决定数据有局部性特性可利用(从而可以划分)、可以批处理;非实时代表响应时间可以较长,有充分的时间执行程序。比如下面的几个操作:
1. 更新搜索引擎排序(在整个web图上执行PageRank算法)
2. 计算推荐(推荐结果并不需要实时更新,因此设定一个固定时间点周期性更新)
MapReduce的诞生有它的时代背景:随着web的发展,尤其是SNS和物联网的发展,web上各种由用户、传感器产生数据量呈现出爆炸式的增长。数据存起来只能是死数据,唯有经过分析处理,才能得到数据中蕴含的信息,进而从信息中总结知识。因此数据重要,处理数据的能力同样重要。传统的基于HPC集群的并行计算已经无法满足飞速增长的数据处理需要,因此基于普通PC的低成本、高性能、高可扩展性、高可靠性的MapReduce应运而生。