MapReduce

短小精悍的简介

MapReduce是Google提出的大规模并行计算解决方案,应用于大规模廉价集群上的大数据并行处理。MapReduce以key/value的分布式存储系统为基础,通过元数据集中存储,数据以chunk为单位分布存储和数据chunk冗余复制来保证高可用性。

MapReduce是一种并行编程模型,将计算阶段分为两个阶段:Map阶段和Reduce阶段。首先把输入数据源分块,交给多个Map任务去执行,Map任务执行Map函数,根据某种规则对数据分类,写入本地硬盘。然后进入Reduce阶段,该阶段由Reduce函数把Map阶段具有相同key值的中间结果收集到相同Reduce结点进行合并处理,并将结果写入本地磁盘。最终结果通过合并Reduce任务的输出得到。

具体问题中,map函数和reduce函数有用户编写。

 

 

Map/Reduce原理

MapReduce是什么?

一个编程模型,处理和生成超大数据集的算法模型的相关实现。

  • 用户创建map函数处理一个基于(key,value)对的数据集合,输出中间基于(key,value)对的数据集合

  • 创建reduce函数合并有相同key值的中间value值

 

MapReduce架构的程序在运行时关心:

  • 如何分割输入数据

  • 大量计算机组成集群的调度

  • 集群中计算机的错误处理

  • 管理集群中计算机之间必要的通信

 

MapReduce编程模型

原理:利用一个输入(key,value)对的集合产生一个输出的(key,value)对的集合。MapReduce库的用户用两个函数表达这个计算:Map和Reduce

用户自定义Map函数接收一个(key,value)集合,产生一个(key,value)集合。MapReduce库把所有具有相同中间key值的中间value值集合在一起后传递给reduce函数。

用户自定义Reduce函数接收一个中间key值和一个相关value值的集合。Reduce函数合并value值,形成较小value值集合。一般,每次Reduce函数产生0/1个输出value值。通常通过迭代器把中间value值给Reduce函数(处理大量value值集合)。

 

MapReduce实现

用户提交工作(job)给调度系统。每个工作(job)包含一系列任务(task),调度系统将这些任务调度到集群中多台可用的机器上

 

MapReduce执行概括

将输入数据分割成M个数据片段的集合,Map调用被分布到多台机器执行。输入的数据片段在不同机器并行处理。分区函数将Map调用产生的中间key分成R个不同分区。Reduce调用也分到多个机器执行。(分区数量R和分区函数由用户指定)

  • MapReduce库把输入文件分M个数据片段,片段大小一般16MB-64MB,可通过特殊参数控制大小。用户程序就在机群中创建大量程序副本

  • 程序副本有一个master,多个worker。master负责分配任务。M个Map任务和R个Reduce任务分配。master将任务分给空闲的worker

  • 被分配了map任务的worker程序读入数据片段,解析出(key,value)对,传给用户定义的Map函数,Map函数生出中间对,缓存在内存中

  • 缓存中的(key,value)对通过分区函数分成R个区域,周期性写入本地磁盘。缓存后的(key,value)对的存储位置回传master,master把位置传给Reduce worker

  • Reduce worker收到存储位置,远程调用从Map worker所在主机的磁盘上读取缓存数据。读取所有中间数据后,通过对key排序使key相同的数据聚合在一起。由于许多不同的key值会映射到相同的Reduce任务,因此必须排序。无法在内存排序,就要在外部排序

  • Reduce worker遍历排序后中间数据,对每个唯一的key,将这个key与关联的中间value的集合传递给用户自定义的Reduce函数。Reduce函数的输出被追加到所属分区的输出文件

  • 当所有Map和Reduce任务都完成,master唤醒用户程序。这时,用户程序里对MapReduce调用才返回

完成任务后,MapReduce输出放在R个输出文件中(每个Reduce产生一个,文件名用户指定)

 

Master数据结构

Master存储每个Map和Reduce任务的状态,以及worker机器的标识。

Master像管道,中间文件存储区域的位置信息通过它从Map传到Reduce。对每个已完成的Map任务,master存储Map任务产生的R个中间文件存储区域的位置和大小。当Map任务完成,Master接收到位置和大小的更新信息,这些信息被推送到Reduce任务

 

容错

  1. worker故障

    master周期性ping每个worker,约定时间没收到回信,标记为失效。所有由此worker完成的map任务重设为初始空闲状态,之后这些任务可被安排给其他worker。同样的,worker失效时正在运行的Map或Reduce任务也将被重新置为空闲状态,等待重新调度

    worker故障时,已经完成Map任务的输出存储在这台机器上,Map任务的输出不可访问,因此必须重新执行。已完成Reduce任务的输出存储在全局文件系统上,不需要再次执行

    一个Map任务首先被worker A执行,worker A失效又被调度到worker B执行,这个“重新执行”动作告知到所有执行Reduce任务的worker。任何还没有从A读取数据的Reduce任务将从B读取数据。

  2. master失效

    让master周期性将上面描述的数据结构写入磁盘,即检查点(checkpoint)。若此master失效,从最后一个检查点开始启动另一个master进程。master只有一个,失效后再恢复较麻烦,因此现在的实现是若master失效,终止MapReduce运算。客户检查到此状态,根据需要重新执行MapReduce操作。

 

失效方面的处理机制

当用户提供的map和reduce操作时输入确定性函数(相同输入产生相同输出)时,分布式实现:在任何情况下的输出都与所有程序没有出现任何错误,顺序执行产生的输出一样。

依赖对map和reduce任务输出时原子提交。每个工作任务把输出写到私有的临时文件中。reduce任务产生一个,map任务产生R个。当map任务完成,worker发送一个包含R个临时文件名的完成消息给master。当master再次收到同样消息,忽略处理。否则,将这R个文件名字记录在数据结构里。

reduce任务完成,reduce worker以原子方式把临时文件重命名为最终的输出文件。若同一个reduce任务多台机器执行,针对同一最终输出文件有多个重命名操作执行。

 

存储位置

网络带宽资源很匮乏。尽量把输入数据存储在集群中机器的本地磁盘上来节省网络带宽。GFS把每个文件按64MB一个block分割,每个block存在多台机器上,环境中存放多份拷贝(一般3个)

MapReduce的master调度map任务时考虑输入文件的位置,尽量将一个map任务调度在包含相关输入数据拷贝的机器上,若失败了,则尝试在保存有数据拷贝的机器附近机器上执行map任务

 

任务粒度

具体实现对R和M又一定客观限制,master必须执行O(M+R)次调度,并在内存中保存O(M*R)个状态

R通常用户指定,因每个reduce任务产生一个独立输出文件。实际使用也倾向于选择合适的M值,以使每个独立任务都处理16M到64M输入数据。

 

备用任务

落伍者:运算过程中,一台机器花很长时间才完成最后几个map或reduce任务,导致MapReduce操作总执行时间超过预期

减少落伍者的机制:当一个MapReduce操作接近完成时,master调度备用(backup)任务进程执行剩下的、处于处理中状态的任务。无论是谁完成了任务,都把这个任务标记为已完成。

 

技巧

  1. 分区函数

    在中间值key上用分区函数对数据进行分区,再输入到后续任务执行进程。缺省分区函数使用hash进行分区。hash能产生非常平衡的分区。

  2. 顺序保证

    确保给定分区中,中间值(key,value)对数据的处理顺序是按照key值增量顺序处理的。保证对每个分区生成一个有序的输出文件。

  3. Combiner函数

    很多情况,map函数产生的key值的重复数据占很大比重,且用户自定义的reduce函数满足结合律和交换律。允许用户指定一个可选的combiner函数,此函数先在本地将这些记录进行一次合并,然后将合并的结果再通过网络发出去。

    conbiner函数在每台执行map任务的机器都执行一次。

    Combiner函数和Reduce函数之间区别:MapReduce库怎样控制函数的输出,reduce函数的输出保存在最终的输出文件里,而conbiner函数的输出被写到中间文件里,发给reduce任务

  4. 输入和输出的类型

    输入类型的实现都必须能把输入数据分割成数据片段, 该片段能由单独的map任务来进行后续处理

    使用者可以通过提高一个简单的Reader接口实现就能支持一个新的输入类型

  5. 副作用

    如果在MapReduce操作过程中增加辅助的输出文件会比较省事。我们依靠程序writer把这种“副作用”变成原子的和幂等的。通常应用程序首先把输出结果写到一个临时文件中,在输出全部数据后,使用系统级的原子操作rename重新命名这个临时文件。

    若产生多个输出文件,并且对于跨文件有一致性要求的任务,都必须是确定性的任务。

  6. 跳过损坏的记录

    程序bug导致MapReduce处理记录时crash掉,操作无法顺利完成。惯常做法是修复bug后再执行。但有时忽略一些有问题的记录可接受。提供一种机制:MapReduce会检查哪些记录导致确定性的crash,并跳过这些记录不处理。

    每个worker进程设置信号处理函数捕获内存段异常和总线错误。执行map或reduce操作之前,MapReduce库用全局变量保存记录序号。若用户程序触发系统信号,消息处理函数用UDP包向master发送处理的最后一条记录的序号。当master看到处理某条记录连续失败,就标记记录需要跳过。下次重新执行时跳过这条记录。

  7. 本地执行

    MapReduce的bug非常难调试。开发了一套MapReduce库的本地实现版本,使用本地版本库,MapReduce操作在本地计算机上顺序的执行。

  8. 状态信息

    master使用嵌入式HTTP服务器显示一组状态信息页面,用户可以监控各种执行状态。用户根据这些数据预测计算需要执行大约多长时间、是否需要增加额外的计算资源等

  9. 计数器

    MapReduce库使用计数器统计不同事件发生次数。用户在程序中创建一个命名的计数器对象,在map和reduce函数中相应增加计数器的值。

    计数器值周期性从单独worker传给master(在ping的应答包中传递)。master执行成功的任务的计数器进行累加,返回给用户。

     

结束语

  1. 约束编程模式使得并行和分布式计算非常容易,也易于构造容错的计算环境

  2. 网络带宽是稀有资源。大量的系统优化是针对减少网络传输量为目的的:本地优化策略使大量的数据从本地磁盘读取,中间文件写入本地磁盘、并且只写一份中间文件也节约了网络带宽

  3. 多次执行相同的任务可以减少性能缓慢的机器带来的负面影响,同时解决了由于机器失效导致的数据丢失问题。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值