本系列为博主个人听课学习笔记,内容整理自西安电子科技大学王琨老师的《云计算与虚拟化》课程
MapReduce 是一种分布式高性能计算场景下编程模型,适用于批处理类的操作,在处理大量读少量写的操作效率很高,大量随机读写的操作效率不高。
MapReduce 封装了并行处理、容错处理、本地化计算、负载均衡等细节。对内实现了相当多自动化的处理过程,对外则提供了简单而强大的接口。
- 容错处理:对计算中可能出现的问题进行处理;
- 本地化计算:“移动程序而不是移动数据,移动计算比移动数据更划算”——若发送处理程序消耗的时间远小于发送待处理文件,那么将程序发送到存储着待处理数据的节点上就非常划算。
本文使用最简单的“单词统计”程序作为示例,该程序的目标是查找出文档中同个单词的出现次数。与单机程序不同的是,该程序中要统计的文档是分散在分布式存储网络中的各个节点上的(且规模可能非常大,以至于单机无法处理)
大体思路比较简单,就是由存储节点统计自己本地文档中的各词词频,结果作为中间结果交给其他的节点进行汇总合并,最终得到结果。
其中,分散总计算就叫 Map,将总计算的中间结果合并再处理就叫 Reduce。中间还有个步骤叫洗牌,洗牌就是 Map 和 Reduce 之间传递中间结果的过程。
下图中,cSlave0 和 cSlave1 各自统计自己本地文档中的词频,得到中间结果后,cSlave0 专门负责统计 china 词频,所以要汇总所有的 china 词频统计的中间结果。cSlave1 同理
MapReduce 编程模型
Map
Map 由 Map 工作机(Map Worker)来进行,每个工作机器【只对一部分原始数据进行处理】。这样的处理是要分布在每个具体存有原始数据的工作机上来进行的。(如果要处理的原始数据多且大,那么这里就能体现出来“移动计算比移动数据更划算”这句话了)
Reduce
- Reduce 由 Reduce 工作机(Reduce Worker)来进行,每个 Reduce 工作机只处理一类工作结果(如上面图中,cSlave0 只处理 china)。
- 每个 Reduce 工作机需要从 Map 工作机来获取它关心的那部分数据(所以上图中的 cSlave0 就只获取了所有的 china 中间统计结果),以供后续计算使用。
- Reduce 工作机的工作也是完全并行的,但其工作要依赖 Map 工作机的结果,每个 Reduce 都需要等待所有的 Map 工作机全部完成各自的工作之后才能完成自身的工作(因为要将各份工作合并嘛,全合并完了才能说所有工作都完成了)。
Map 和 Reduce 函数
Map
- 两个参数分别指明要处理的数据的位置和大小,即说明要处理哪部分数据。
- 运算结果是一组<key, value>对,这一组有序对是 Map 运算结束后产生的中间结果(后续会交给 Reduce)。
Reduce
- Map 产生的中间结果需要经过系统的归并处理。具体操作就是将各个 Map 工作机产生的结果中相同 key 所对应的一系列 value 合并到一起,成为形如 (key, [value1, value2, ..., valuen]) 的值。再将这个值作为参数输入到一个 Reduce 工作机进行归并处理(因为每个 Reduce 工作机只处理其关心的事务,所以送到每个 Reduce 工作机的值都有着相同的 key)。
- 每个 Reduce 工作机都处理一个 key (key, final_value),最终所有的 Reduce 工作机的工作结果合并到一起,就能得到我们想要的最终结果了。
在实际应用中,Map 和 Reduce 可以进行多次迭代计算,比如将一次 Reduce 得到的结果重新 Map 之后再 Reduce。
MapReduce 实现机制
在具体的 MapReduce 过程中涉及一些复杂的问题,比如:
- 分割好的数据怎么去找工作机呢?要考虑哪些因素呢?
- 任务分配到工作机后,出现故障怎么办?
- Map 工作机、Reduce 工作机的任务执行完之后怎么相互通知?Map 工作机完全并行处理,之间没有什么关联。但 Reduce 是直接依赖 Map 的,那么 Reduce 工作机怎么去找 Map 工作机要数据?如何对工作流程进行控制?
粗略的方案如下:
- MapReduce 函数先将输入文件分块,具体分块尺寸可以根据情况控制。用户程序将对 Map、Reduce 工作机要进行的任务的分割方案交给主控程序(主控程序是负责管理整个 MapReduce 系统的任务管理和分配,一个 MapReduce 系统可以有多个主控程序,进行多个不同的任务管理。运行主控程序的节点就是这次 MapReduce 计算的计算主节点,即,Master。这个 Master 与 GFS 的那个 Master 不是同一个,一般来说该 Master 在成为 Master 之前只是一个普通的存储节点。只不过这次被 MapReduce 通过某些规则选中了暂时当一下 Master,管理此次的计算任务);
- 主控程序和文件系统进行通信(比如 GFS 的 Master Server),以确定要被处理的数据都在哪些节点上。在找第一步Map工作机的策略大概如此:因为同一份数据被存储在多个节点上,因此可以在该数据所存在的多个节点中寻找相对空闲的节点,并将程序发送给这个节点;
- 主控程序告知这个节点需要处理的数据的地址,这个节点就可以开始处理本地数据了。每个 Map 工作机在运行时,都是从自己本地的硬盘中读出数据进行处理,此时产生的每个中间结果<key, value>对先放在内存的缓冲区中;
- Map 工作机会定时将内存缓冲区中的中间结果写入到本地硬盘中,也就是边处理边落盘中间结果。Map 工作机完成自己的工作后,通知主控程序已经完成了自己这部分工作,并将中间结果在自己磁盘中的位置发送给主控程序;
- 主控程序通知相关的 Reduce 工作机,告知其需要进行处理的中间结果在哪个节点的什么位置。然后,这些 Reduce 工作机就会对那个节点进行 RPC 调用,读取这些中间数据。每当有一个新的 Map 工作机完成任务,都会进行一遍这样的操作;
- Reduce 工作机完成自己的任务后输出结果。所有任务结束,通知用户取走所有的数据。这些数据合并后就是用户想要的数据
在 Map、Shuffle、Reduce 以及存储结果的这些阶段中,各个阶段都是并行执行的。整个过程构成一个有向无环图(DAG)
全过程如此:
MapReduce 容错机制
MapReduce 通过重新执行失效的地方来实现容错
Master (主控程序所在节点)失效
Master 需要为整个并行运算系统进行协调和控制,因此需要重点保护。
- Master 周期性设置检查点(Checkpoint)并在此导出 Master 的数据,一旦某个任务失效(比如某个 Map/Reduce 工作机出错,或者 master 本身出现了不太严重的问题),系统就从最近一个检查点恢复并重新执行(我觉得相当于进行状态快照)。
- 若 Master 自己挂了(失效),需要终止整个 MapReduce 程序并重新运行。系统要重新找一个 master,重新进行调度,再来一遍。。
Worker 失效
- Master 会周期性 ping 各个工作机,ping 不通就认为这个工作机失效了,然后把这个工作机的任务调度给其他的工作机重新执行。