本系列目录
MIT 6.824 学习笔记
Lab 1 测试脚本解读
这篇文档解释 `test-mr.sh` 里每个测试在验证什么,以及测试失败时该怎么排查。
运行测试#
cd labs/src/main
bash test-mr.shbash测试会在 mr-tmp/ 目录下运行,所有中间文件和输出文件都在这里。
测试 1:wc(词频统计)#
验证什么:基本正确性。你的分布式 MapReduce 输出结果是否和单机顺序执行一致。
测试流程:
- 先用
mrsequential生成正确答案mr-correct-wc.txt - 启动 Master 和 3 个 Worker
- 等待所有进程退出
- 把所有
mr-out-*文件合并排序,和正确答案对比
失败原因:
- 输出文件内容不对:Map 或 Reduce 逻辑有 bug
- 输出文件缺失:某些 Reduce 任务没有完成
- 程序超时(180秒):死锁或无限循环
测试 2:indexer(倒排索引)#
验证什么:处理复杂 key/value 的能力。indexer 的 value 是文件名列表,比 wc 复杂。
失败原因:
- 中间文件读取不完整:Reduce 任务没有读取所有对应的中间文件
- JSON 编解码错误:中间文件格式不对
测试 3:map parallelism(Map 并行性)#
验证什么:Map 任务是否真的并行执行。
测试原理:mtiming.go 里的 Map 函数会记录执行时间。测试脚本检查是否有多个 Map 任务在同一时间段内执行。
失败原因:
- Master 串行分配任务(一次只分配一个任务,等完成后再分配下一个)
- 正确做法:Master 应该同时分配多个任务给不同的 Worker
测试 4:reduce parallelism(Reduce 并行性)#
验证什么:Reduce 任务是否真的并行执行。
失败原因:
- Map 阶段和 Reduce 阶段的切换逻辑有 bug
- 比如:Map 还没全部完成就开始分配 Reduce 任务
测试 5:crash(崩溃容错)#
验证什么:Worker 随机崩溃时,系统是否还能正确完成任务。
测试原理:crash.go 里的 Map/Reduce 函数会随机 os.Exit(1) 来模拟崩溃。
失败原因:
- 没有实现超时检测:Worker 崩溃后,任务永远不会被重新分配
- 输出文件损坏:Worker 崩溃时正在写文件,留下了不完整的文件
- 解决方案:用原子写入(先写临时文件,再 rename)
- 重复执行导致结果错误:同一个任务被执行了两次,输出了两份结果
- 解决方案:用原子 rename,第二次 rename 会覆盖第一次的结果,不会有问题
调试技巧#
查看输出文件:
ls mr-tmp/mr-out-*
cat mr-tmp/mr-out-0bash查看中间文件:
ls mr-tmp/mr-*-*bash手动运行单个测试:
cd mr-tmp
../mrmaster ../pg*txt &
sleep 1
../mrworker ../../mrapps/wc.so &
../mrworker ../../mrapps/wc.so
wait
sort mr-out* | grep . > mr-wc-all
diff mr-wc-all mr-correct-wc.txtbash加日志调试:
在 master.go 和 worker.go 里加 log.Printf 语句,然后运行测试,观察日志输出。
bash test-mr.sh 2>&1 | head -100bash测试通过的标志#
*** Starting wc test.
--- wc test: PASS
*** Starting indexer test.
--- indexer test: PASS
*** Starting map parallelism test.
--- map parallelism test: PASS
*** Starting reduce parallelism test.
--- reduce parallelism test: PASS
*** Starting crash test.
--- crash test: PASS
*** PASSED ALL TESTSplaintext