《Data-intensive Text Processing with MapReduce》读书笔记第2章:MapReduce基础(2)
本读书笔记的目录地址:http://www.cnblogs.com/mdyang/archive/2011/06/29/data-intensive-text-prcessing-with-mapreduce-contents.html
2.3 执行框架
MapReduce最伟大的地方在于它分离了编写并行算法的what和how(你只需要写程序,而不需要为它怎么执行操心). 而对这一点贡献颇大的就是执行框架:它处理了几乎所有底层执行的细节,并且能够保证MapReduce集群具有从几个节点增长到数千节点的扩展能力。具体来说,包括以下一些职责:
1) 调度
每项MapReduce工作(job)都被分解为多个任务(task)。例如map任务负责处理一堆输入key-value对(这在Hadoop中成为输入分割);reduce任务处理中间结果的key-value对。在MapReduce中有数千项任务等待分配是很正常的事。对于一些大规模计算程序来说,等待分配的任务数甚至会超过可同时(并发)执行的任务数,这样一来,就有了对调度的需求。具体说来有两方面:1. 对于单个工作来说,需要执行的任务太多时,需要维护任务队列,处理执行顺序;2. 对于有来自不同用户的多个工作同时执行的情况,需要保证共享访问的可控性、稳定性、正确性。
预测执行(speculative execution)是MapReduce中(Google MapReduce与Hadoop均实现了这一特性)针对任务调度的一个优化措施。
预测执行解决的是掉队者(straggler)问题。关于掉队者的描述:无论对于map阶段还是reduce阶段,执行完毕的时刻取决于最慢的那个执行任务执行完毕的时刻。这个最慢的任务称为“掉队者(straggler)”。造成掉队的原因有很多:硬件问题(有的机器出现故障但仍能正确工作,只是变得很慢)、数据划分不均匀(造成有的任务小,有的任务大)等。
预测执行解决掉队的方法是在另一台机器上执行一个相同任务的拷贝,当这两个任务有一个完成时,即认为任务已完成。
2) 数据/代码协同放置
MapReduce与传统并行编程模型的本质区别在于它移动了程序代码:MapReduce将程序分发到各个数据节点上执行。这么做的核心思想是更好地利用数据局部性,避免数据移动。局部性根据集群结构分为很多层次,取决于需要访问的数据量和网络带宽/延迟:
数据量:单机<机架<数据中心
带宽/延迟:单机>同一机架内单机间>同一数据中心内机架间>数据中心间
3) 同步
这一部分讲的其实是关于map生成中间结果与reduce接受中间结果之间的执行序问题。
通常来说,当多个对于共享资源的访问“碰头”的时候,我们就该考虑同步问题了。对于MapReduce来说,这个共享资源就是中间结果:mapper生产中间结果,而紧接其后的reducer消费中间结果。先来回顾一下MapReduce的执行过程:mapper处理key-value对以后,输出中间结果key-value对;中间结果key-value对按照key进行分组、排序之后,输入reducer进行处理。下面是两个MapReduce中的事实:
- MapReduce中,reduce任务在所有中间结果key-value对生成完毕并且分组、排序好之前,是不能够启动的;
- MapReduce中间结果key-value对通过网络传输(m个mapper→n个reducer,需要m×n个传输操作)。
但等到所有mapper执行完毕再传输计算结果效率是很低的。因此Hadoop进行了很常见的优化:map与中间结果key-value对的传输异步、交错执行(边map,边将生成的中间结果传输给reducer);而mapper-reducer之间则遵循严格的执行序(所有mapper完毕且中间结果传输后,reducer启动)。
4) 错误与故障处理
MapReduce运行在由大量普通PC机构成的集群之上,在这样的环境中,单点故障是很常见的。
硬件:磁盘故障、内存错误、数据中心无法访问(计划中:硬件升级;计划外:断网、断电)
软件错误
2.4 Partitioner与Combiner(划分器与合并器)
通过前三节已经对MapReduce有了基本的认识,接下来介绍划分器与合并器,有了这两个要素,MapReduce编程模型就基本完整了。
1) 划分器
划分器的主要任务是将中间结果key-value对进行划分,以决定将其分配至哪个reducer.
最简单的一种做法就是对key值hash后取模,结果作为reducer的编号:
假设有r个reducer,编号为0,1...r-1,则有reduceri←(k1,v1),其中i=hash(k1) mod r
这个划分方法可以保证key分布的均匀性(每个reducer持有的key值种数几乎一样多),但不能保证key-value对分布的均匀性,因此某些情况下会造成数据偏斜:
比如说对于单词统计,reducer1分配到了所有的("hadoop",1),reducer2分配到了所有的("the",1),虽然从key上看,reducer1和reducer2持有的key数是一样的(都是1),但由于"hadoop"的出现次数远远低于"the",因此("hadoop",1)的数量大大少于("the",1)的数量,从而导致reducer1只分配到很少数据,而reducer2分配到大量数据。
2) 合并器
合并器是一种优化手段,它在mapper输出中间结果后、中间结果分组/排序前执行一个局部合并的操作。例如对于单词统计应用,在将mapper产生的(word,1)发送出去之前,可先对其进行合并。例如mapper1产生("c",3),("c",6),合并器会将其合并为("c",9)再输出。这样,每个mapper输出的key-value对数至多为该mapper处理的文档中所含不同单词的数量。
图2.4 完整的MapReduce模型 (加入了合并器的单词统计程序) |
从这个意义上说,合并器可以看成是一个迷你reducer,它处理的数据局限在某一个mapper的输出中。合理地使用合并器可提高算法效率。完整的MapReduce编程模型见图2.4.