【MapReduce】超大集群的简单数据处理 part3

 

3.2 Master的数据结构

 

master需要保存一定的数据结构。对于每一个mapreduce任务来说,都需要保存它的状态(idlein-progress或者completed),并且识别不同的worker机器(对于非idel的任务状态)。

master是一个由map任务产生的中间区域文件位置信息到reduce任务的一个管道。因此,对于每一个完成得map任务,master保存下来这个map任务产生的R中间区域文件信息的位置和大小。对于这个位置和大小信息是当接收到map任务完成得时候做的。这些信息是增量推送到处于in-progress状态的reduce任务的worker上的。

 

3.3 容错考虑

 

由于MapReduce函数库是设计用于在成百上千台机器上处理海量数据的,所以这个函数库必须考虑到机器故障的容错处理。

 

Worker失效的考虑

master会定期ping每一个worker机器。如果在一定时间内没有worker机器的返回,master就认为这个worker失效了。所有这台worker完成的map任务都被设置成为他们的初始idel状态,并且因此可以被其他worker所调度执行。类似的,所有这个机器上正在处理的map 任务或者reduce任务都被设置成为idle状态,可以被其他worker所重新执行。

在失效机器上的已经完成的map任务还需要再次重新执行,这是因为中间结果存放在这个失效的机器上,所以导致中间结果无法访问。已经完成的recude任务无需再次执行,因为他们的结果已经保存在全局的文件系统中了。

map任务首先由Aworker执行,随后被Bworker执行的时候(因为A失效了),所有执行reduce任务的worker都会被通知。所有还没有来得及从A上读取数据的worker都会从B上读取数据。

MapReduce可以有效地支持到很大尺度的worker失效的情况。比如,在一个MapReduce操作中,在一个网络例行维护中,可能会导致每次大约有80台机器在几分钟之内不能访问。MapReducemaster制式简单的把这些不能访问的worker上的工作再执行一次,并且继续调度进程,最后完成MapReduce的操作。

 

Master失效

 

master中,定期会设定checkpoint,写出master的数据结构。如果master任务失效了,可以从上次最后一个checkpoint开始启动另一个master进程。不过,由于只有一个master在运行,所以他如果失效就比较麻烦,因此我们当前的实现上,是如果master失效了,就终止MapReduce执行。客户端可以检测这种失效并且如果需要就重新尝试MapReduce操作。

 

失效的处理设计

当用户提供的mapreduce函数对于他们的输入来说是确定性的函数,我们的分布式的输出就应当和在一个整个程序没有失败的连续执行相同。

我们依靠对mapreduce任务的输出进行原子提交来完成这样的可靠性。每一个in-progress任务把输出写道一个私有的临时文件中。reduce任务产生一个这样的文件,map任务产生R个这样的任务(每一个对应一个reduce任务)。当一个map任务完成的时候,worker发送一个消息给master,并且这个消息中包含了这个R临时文件的名字。如果master又收到一个已经完成的map任务的完成消息,他就忽略这个消息。否则,他就在master数据结构中记录这个R文件。

当一个reduce任务完成的时候,reduce worker自动把临时输出的文件名改为正式的输出文件。如果再多台机器上有相同的reduce任务执行,那么就会有多个针对最终输出文件的更名动作。我们依靠文件系统提供的原子操作改名字,来保证最终的文件系统状态中记录的是其中一个reduce任务的输出。

我们的绝大部分mapreduce操作都是确定性的,实际上在语义角度,这个mapreduce并发执行和顺序执行市一样的,这就使得程序员很容易推测程序行为。当mapreduce操作是非确定性的时候,我们有稍弱的但是依旧是有道理的错误处理机制。对于非确定性操作来说,特定reduce任务R1的输出,与,非确定性的顺序执行的程序对R1的输出是等价的。另外,另一个reduce任务R2的输出,是和另一个顺序执行的非确定性程序对应的R2输出相关的。

考虑map任务Mreduce任务R1R2。我们设定e(Ri)为已经提交的Ri执行(有且仅有一个这样的执行)。当e(R1)处理得是M的一次执行,而e(R2)是处理M的另一次执行的时候,那么就会导致稍弱的失效处理了。

 

3.4 存储位置

 

在我们的环境下,网络带宽资源是相对缺乏的。我们用尽量让输入数据保存在构成集群机器的本地硬盘上(通过GFS管理[8])的方式来减少网络带宽的开销。GFS把文件分成64M一块,并且每一块都有几个拷贝(通常是3个拷贝),分布到不同的机器上。MapReducemaster有输入文件组的位置信息,并且尝试分派map任务在对应包含了相关输入数据块的设备上执行。如果不能分配map任务到对应其输入数据的机器上执行,他就尝试分配map任务到尽量靠近这个任务的输入数据库的机器上执行(比如,分配到一个和包含输入数据块在一个switch网段的worker机器上执行)。当在一个足够大的cluster集群上运行大型MapReduce操作的时候,大部分输入数据都是在本地机器读取的,他们消耗比较少的网络带宽。

3.5 任务颗粒度

 

如果上边我们讲的,我们把map阶段拆分到M小块,并且reduce阶段拆分到R小块执行。在理想状态下,MR应当比worker机器数量要多得多。每一个worker机器都通过执行大量的任务来提高动态的负载均衡能力,并且能够加快故障恢复的速度:这个失效机器上执行的大量map任务都可以分布到所有其他worker机器上执行。

但是我们的实现中,实际上对于MR的取值有一定的限制,因为master必须执行O(M+R)次调度,并且在内存中保存O(M*R)个状态。(对影响内存使用的因素还是比较小的:O(M*R)块状态,大概每对map任务/reduce任务1个字节就可以了)

进一步来说,用户通常会指定R的值,因为每一个reduce任务最终都是一个独立的输出文件。在实际中,我们倾向于调整M的值,使得每一个独立任务都是处理大约16M64M的输入数据(这样,上面描写的本地优化策略会最有效),另外,我们使R比较小,这样使得R占用不多的worker机器。我们通常会用这样的比例来执行MapReduce: M=200000R=5000,使用2000worker机器。

3.6 备用任务

 

通常情况下,一个MapReduce的总执行时间会受到最后的几个拖后腿的任务影响:在计算过程中,会有一个机器过了比正常执行时间长得多的时间还没有执行完map或者reduce任务,导致MapReduce总任务不能按时完成。出现拖后腿的情况有很多原因。比如:一个机器的硬盘有点问题,经常需要反复读取纠错,然后把读取输入数据的性能从30M/s降低到1M/scluster调度系统已经在某台机器上调度了其他的任务,所以因为CPU/内存/本地硬盘/网络带宽等竞争的关系,导致执行MapReduce的代码性能比较慢。我们最近出现的一个问题是机器的启动代码有问题,导致关闭了cpucache:在这些机器上的任务性能有上百倍的影响。

我们有一个通用的机制来减少拖后腿的情况。当MapReduce操作接近完成的时候,master调度备用进程来执行那些剩下的in-progress状态的任务。无论当最初的任务还是backup任务执行完成的时候,都把这个任务标记成为已经完成。我们调优了这个机制,通常只会占用多几个百分点的机器资源。但是我们发现这样做以后对于减少超大MapReduce操作的总处理时间来说非常有效。例如,在5.3节描述的排序任务,在关闭掉备用任务的情况下,要比有备用任务的情况下多花44%的时间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值