2004 年发表了 MapReduce 的论文,是一个分布式计算的框架。
当你仔细了解 MapReduce 的框架之后,你会发现 MapReduce 的设计哲学和 Unix 是一样的,叫做“Do one thing, and do it well”,也就是每个模块只做一件事情,但是把这件事情彻底做好。
作为一个框架,MapReduce 设计的一个重要思想,就是让使用者意识不到“分布式”这件事情本身的存在。从设计模式的角度,MapReduce 框架用了一个经典的设计模式,就是模版方法模式。而从设计思想的角度,MapReduce 的整个流程,类似于 Unix 下一个个命令通过管道把数据处理流程串接起来。
MapReduce 的数据处理设计很直观,并不难理解。Map 帮助我们解决了并行在很多台机器上处理互相之间没有依赖关系的数据;而 Reduce 则用来处理互相之间有依赖关系的数据,我们可以通过 MapReduce 框架自带的 Shuffle 功能,通过排序来根据设定好的 Key 进行分组,把相同 Key 的数据放到同一个节点上,供 Reduce 处理。
而作为 MapReduce 框架的使用者,你只需要实现 Map 和 Reduce 两个函数,并且指定输入输出路径,MapReduce 框架就会帮助你完成整个数据处理过程,不需要你去关心整个分布式集群的存在。另外,不仅仅是 MapReduce 的用户,只需要考虑“单一职责”,实现自己的 Map 和 Reduce 函数就好了。即使作为 MapReduce 的框架实现,也能够把数据读取、数据输出、网络传输、数据混洗等模块单独拆出来,实现起来也很容易。
Map 和 Reduce 这两个函数虽然非常简单,但是对于输入输出的格式,以及内部具体的逻辑代码没有任何限制,是完全灵活的,足以完成从日志分析、网页处理、数据统计,乃至于搜索引擎的索引生成工作。
事实上,我们在论文中也可以看到,谷歌在多种不同的场景中,都使用了 MapReduce,包括:
MapReduce 的实现是比较简单的,就是一个典型的单 master 多 worker 组成的主从架构。在分布式系统容错上,MapReduce 也采取了简单的重新运行、再来一次的方案。对于 master 这个单点可能出现的故障,谷歌在最早的实现里,根本就没有考虑失效恢复,而是选择了任由 master 失败,让开发人员重新提交任务重试的办法。
还有一点也和 GFS 一样,MapReduce 论文发表时的硬件,用的往往是 100MB 或者 1GB 的网络带宽。所以 MapReduce 框架对于这一点,就做了不少性能优化动作。通过尽量让各个 worker 从本地硬盘读取数据,以及通过 Combiner 合并本地 Map 输出的数据,来尽可能减少数据在网络上的传输。
而为了方便开发人员去 debug 程序,以及监控程序的执行,MapReduce 框架通过 master 内嵌的 Web 服务器,展示了所有 worker 的运行情况和日志。你还可以通过自定义的计数器,统计更多你觉得有价值的信息。
当然,MapReduce 里还有备用任务(Backup Tasks)、自定义的 Partitioner 等更多的细节值得你去探索。这些就留给你去仔细研读论文,好好琢磨了。
尽管 MapReduce 框架已经作出了很多努力,但是今天来看,整个计算框架的缺陷还是不少的。在我看来,主要的缺陷有两个:
不过,随着时间的变迁,会有更多新一代的系统,像是 Dremel 和 Spark 逐步取代 MapReduce,让我们能更容易地写出分布式数据处理程序,处理起数据也比原始的 MapReduce 快上不少。
参考
http://nathanmarz.com/blog/the-mathematics-behind-hadoop-based-systems.html