概述

这次我们要处理worker故障.

  • master通过调用common_rpc.go: call()来分配任务.当超时发生, 该函数 返回false, 这时候master要把该任务重新分配给另一个worker.
  • common_rpc.go: call()返回false不等于执行失败, worker可能执行得比较慢导致超时.这样可能导致, 实际上有多个worker在执行同一个task(对于master来说, 只有一个).
  • 此外, mapreduce通过GFS保证task的输出是完整的和原子的(要么全部文件都输出, 要么都不输出), 这个实验并没有实现这个保证, 之间简单地令worker crash.

问题

面对worker故障, 我们应该如何调整schedule()的代码?

当所有task都被完成了, schedule就结束, 那么如何跟踪每个task的状态?

有别于论文, 实验中可能出现的故障有(按阶段分类):

  • 执行map阶段发现worker crash, 重新分配task
  • map阶段结束, 中间输出已写入到本地disk, mapper不可访问, 但由于实验是多线程模拟分布式环境, 所有内容都是可见的, 这些中间结果也是可访问的.
  • 执行reduce任务出错, 重新分配该任务即可。
  • reduce执行完毕, reducer出故障, 结果也是可访问的, 所以不予考虑.
  • worker向disk输出结果(包括中间文件、job result)出错。这里没有GFS, 只是简单地让worker crash。所以也等于执行task中出错。

所以我们只需要考虑: task执行失败如何处理。这个只需要重新分配task即可。

实现

如何跟踪Task?

  • 通过chan来接受完成的Task的index,这里要用一个map来记录哪些完成了,有没有重复。访问这个map要通过锁。
  • 或者用一个原子类型的数组,通过原子操作Atomic.Storexxx()来记录。

如何重新分配Task?
main产生dispatcher和tracker两个goroutine。dispatcher生成多个controller,也就是某个Task的rpc handler。如下图。

            Taskid
   ------← ToDoChan ←------   
   ↓                    任务失败
   ↓                       ↑
dispatcher -------> controller 
  ↑                       ↓
  ↑                     任务完成 ----------> tracker
  ↑                     ↓          Taskid
  ↑           workerid  ↓      
  ↑---------------  registerChan

那么如何中止?dispatcher各自检测到nTask个任务都完成后自行中止。


Tsukami
9 声望9 粉丝

语雀: [链接]


下一篇 »
MIT6.824-Lab1-P3