MapReduce读书报告 MapReduce: Simplified Data Processing on Large Clusters

MapReduce读书报告

MapReduce: Simplified Data Processing on Large Clusters

 

作者和许多Google员工在工作中实现了许多特殊用途的计算,其中包括了处理大量的数据(网络请求日志,抓取的文档等),计算各种派生数据(倒排索引等)。大多数这样的计算都很简单,但是输入数据量通常很大。计算过程需要分布到数百或数千台计算机上进行,才能保证在一个合理的时间内完成计算过程。可是处理计算的并行化、数据分发和错误处理等的代码量巨大且很复杂,使得计算过程的编码变得难懂。

受到了Lisp等函数式语言中的map和reduce原语的启发,作者设计了MapReduce。MapReduce将涉及并行、容错性、数据分发和负载均衡的细节隐藏在一个函数库中,从而降低计算过程的复杂性。大多数的计算都包含了在每个输入的逻辑记录上应用map操作,从而计算出一组中间key/value对的集合,然后再向共享相同key的所有中间value应用reduce操作,从而适当地合并派生数据。MapReduce中用户定义的map和reduce操作的使用可以轻松地将大型计算并行化,以及将再执行作为容错性的主要机制。


MapReduce的编程模型

计算过程就是输入一组key/value对,再生成输出一组key/value对。MapReduce库的使用者用两个函数来表示这个过程:map和reduce。

map由用户编写,使用一个输入key/value对,生成一组中间key/value对。MapReduce库将有着相同中间key I的中间value都组合在一起,再传给reduce函数。

reduce也由用户编写,它接受一个中间key I和一组与I对应的value。它将这些value合并为一个可能更小的value集合。通常每个reduce调用只产生0或1个输出value。中间value是通过一个迭代器提供给reduce函数的。这允许操作那些因为太大到找不到连续存放的内存而使用链表的value集合。

map (k1, v1) → list(k2, v2)

reduce (k2, list(v2)) → list(v2)

输入的key和value与输出的key和value的域不同,中间的key和value与输出的key和value的域相同。


MapReduce的执行过程 

图1展示了MapReduce操作的整体流程。当用户程序调用MapReduce函数时,会发生下面一系列动作:

  1. 用户程序中的MapReduce库首先将输入文件切分为M块,每块的大小从16MB到64MB(可通过一个可选参数控制块大小)。然后MapReduce库会在一个集群的若干台机器上启动程序的多个副本。
  2. 程序的各个副本中有一个是主节点,其它的则是工作节点。主节点将M个map任务和R个reduce任务分配给空闲的工作节点。
  3. 被分配map任务的工作节点读取对应的输入区块内容。它从输入数据中解析出key/value对,然后将每个对传递给用户定义的map函数。由map函数产生的中间key/value对都缓存在内存中。
  4. 缓存的数据对会被周期性的由划分函数分成R块,并写入本地磁盘中。这些缓存对在本地磁盘中的位置会被传回给主节点,主节点负责将这些位置再传给reduce工作节点。
  5. 当一个reduce工作节点得到了主节点传递的缓存对位置后,它使用远程过程调用去读map工作节点的本地磁盘中的缓存数据。当reduce工作节点读取完了所有的中间数据,它会将这些数据按中间key排序,这样相同key的数据就被排列在一起了。
  6. reduce工作节点遍历排序好的中间数据,并将遇到的每个中间key和与它关联的一组中间value传递给用户的reduce函数。reduce函数的输出会写到由分区的最终文件中。
  7. 当所有的map和reduce任务都完成后,主节点唤醒用户程序。此时,用户程序中的MapReduce调用返回到用户代码中。

成功完成后,MapReduce执行的输出都在R个输出文件中(每个reduce任务产生一个,文件名由用户指定)。通常用户不需要合并这R个输出文件——他们经常会把这些文件当作另一个MapReduce调用的输入,或是用于另一个可以处理分成多个文件输入的分布式应用。

 

主节点的数据结构

主节点维持多种数据结构。它会存储每个map和reduce任务的状态(空闲、处理中、完成),和每台工作机器的ID(对应非空闲的任务)。

主节点是将map任务产生的中间文件的位置传递给reduce任务的通道。因此,主节点要存储每个已完成的map任务产生的R个中间文件的位置和大小。位置和大小信息的更新情况会在map任务完成时接收到。这些信息会被逐步发送到正在处理中的reduce任务节点处。


MapReduce的容错性

MapReduce使用成百上千台机器处理数量非常大的数据,就必须具有优秀的容错能力。

1.工作节点错误

MapReduce可以弹性应对大范围的工作节点失败。主节点周期性的ping每个工作节点。如果工作节点在一定时间内没有回应,主节点就将它标记为已失败。这个工作节点完成的任何map任务都被重置为空闲状态,并可被调度到其它工作节点上。同样地,失败的工作节点上正在处理的任何map或reduce任务也被重置为空闲状态,允许被调度。

失败节点上已完成的map任务需要重执行的原因是它们的输出存储在失败机器的本地磁盘上,因此无法访问到了。已完成的reduce任务不需要重执行,因为它们的输出存储在了一个全局文件系统上。

当一个map任务先被A节点执行过,随后又被B节点重执行(A节点已失败),所有执行reduce任务的工作节点都能收到重执行的通知。任何没有读取完A节点数据的reduce任务都会从B节点读取数据。

2.主节点错误

一种简单的方法是令主节点定期将上面描述的数据结构保存为恢复点。如果主节点任务失败,就可以从上一个恢复点状态启动一个新的程序副本。但是给定的条件是只有一个主节点,它也不太可能失败;因此MapReduce当前的实现会在主节点失败时中止MapReduce计算 。用户可以检查到这一情况,并在需要时重启MapReduce操作。


MapReduce的局部性

在Google的计算环境中,网络带宽是一种比较稀缺的资源。作者利用下面的方法来节省带宽:输入数据(由GFS管理)就存储在组成集群的机器的本地磁盘上。GFS将每个文件分成64MB大小的区块,每块复制若干份(通常为3份)存储到不同的机器上。MapReduce主节点会把输入文件的位置信息考虑进去,并尝试将map任务分配到保存有相应输入数据的机器上。如果失败的话,它会试图将map任务调度到临近这些数据的机器上(例如与保存输入数据的机器处于同一网关的工作节点)。当在一个集群的相当一部分节点上运行MapReduce操作时,大多数输入数据都是本地读取,并不消耗网络带宽。


MapReduce的任务粒度

MapReduce将map阶段分成M份,将reduce阶段分成R份。理想情况下,M和R应该比工作节点机器的数量大很多。每个工作节点处理很多不同的任务,可以增强动态负责均衡能力,也能加速有工作节点失败时的恢复情况:失败节点已经完成的map任务有很多的时候也能传递给其它所有工作节点来完成。

在我们的实现中M和R的数量有一个实际的上限:如上所述,主节点必须做O(M+R)的调度决定以及在内存中保持O(M*R)个状态。其中R通常由用户指定,因为每个reduce任务都会产生一个独立的输出文件。在实践中倾向于将每个单独的任务分成16-64MB大的输入数据(此时局部性优化效果最好)。


MapReduce的备用任务

导致MapReduce操作用时延长的一个常见原因是出现了“落后者”:某台机器在完成最后的一个map或reduce任务时花费了反常的漫长时间。一个通用的机制来减轻落后者问题:当MapReduce操作接近完成时,主节点会将仍在处理中的剩余任务调度给其它机器作备用执行。原本的执行和备用执行中的任一个完成时都会将对应任务标记为已完成。这个机制有效地减少了大型MapReduce操作花费的时间,增加的计算资源消耗通常只有一点点。


MapReduce的扩展

1.划分函数

MapReduce的用户指定他们想要的reduce任务/输出文件的数量。通过划分函数可以将数据按中间key划分给各个reduce任务。

2.合并函数

某些情况中,不同的map任务产生的中间key重复率非常高,而且用户指定的reduce函数可进行交换组合。MapReduce允许用户指定一个可选的合并函数,在数据被发送之前进行局部合并。

合并函数由每个执行map任务的机器调用。通常合并函数与reduce函数的实现代码是相同的。它们唯一的区别就是MapReduce库处理函数输出的方式。reduce函数的输出会写到最终的输出文件中,而合并函数的输出会写到中间文件中,并在随后发送给一个reduce任务。

3.顺序保证

MapReduce保证在给定的划分中,中间key/value对是按增序排列的。这个顺序保证使每个划分产生一个有序的输出文件变得很容易。当输出文件的格式需要支持高效的按key随机访问,或用户需要输出数据有序时,这一性质会非常有用。

4.跳过坏记录

有时用户代码中的bug会导致map或reduce函数一遇到特定的记录就崩溃。这些bug会导致MapReduce操作无法完成。MapReduce提供了一个可选的执行模式,在MapReduce检测到确定会导致崩溃的记录时跳过它们从而继续执行。

5.本地执行

为了帮助调试、性能分析、小范围测试,Google开发了MapReduce库的一个替代实现,可以将MapReduce操作的全部工作在一台本地机器上顺序执行。用户拥有控制权,因此计算可以被限制在特定的map任务中。用户调用他们的程序时加上一个特殊标志,就可以方便的使用任何有用的调试或测试工具。

6.状态信息

主节点内置了一个HTTP服务器,可以将当前状态输出为一组网页供用户使用。状态网页能显示计算的进度,例如有多少任务被完成,多少正在处理等等。这些网页还包含指向每个任务的stdout和stderr输出文件的链接。用户可以用这些数据来预测计算要花费多长时间,以及是否应该增加计算使用的资源。这些网页也能用于在计算速率比预期慢很多时发现这一情况。另外,顶层的状态网页还能显示哪些工作节点失败了,它们失败时正在处理哪些map和reduce任务。当要在用户代码中确定bug时这些时间非常有用。


MapReduce的优缺点

优点:

  1. MapReduce即使是对于没有并行和分布式系统经验的程序员也是很易于使用的,因为它隐藏了并行化、容错机制、局部性优化、以及负载平衡的细节,同时可以分布到大量廉价的PC机器运行。
  2. 当计算机资源不能得到满足的时候,可以通过简单的增加机器来扩展它的计算能力。
  3. 高容错性。

缺点:

  1. 实时计算:MapReduce启动前必须要划分数据,复制数据等,无法像Oracle或MySQL那样在毫米或秒级内返回结果。
  2. 流计算:流计算的输入数据是动态的,而MapReduce自身的设计特点决定了数据源必须是静态的。
  3. 有向图计算:多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce使用后,每个MapReduce作业的输出结果都会写入磁盘,会造成大量的词频IO导致性能非常低下。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值