概述
这次我们要处理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个任务都完成后自行中止。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。