MIT6.824 Lab1 MapReduce

本文档介绍如何使用Go语言实现MapReduce库,包括MapReduce的主要机制、软件需求、代码结构和实现流程。实验涉及串行和分布式MapReduce,以及处理worker故障。此外,还详细解释了word count的实现,并提供了分布式的Map/Reduce任务和worker故障处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction
  本次实验主要是用go语言来实现1个MapReduce库,并且了解分布式系统的容错机制,推荐先看一下MapReduce的论文[MapReduce]
  主要机制如下图:
  这里写图片描述
  Map worker读入1个文件,处理后生成n(reduce worker数目)个中间文件,然后每个Reduce worker读取其对应的所有中间文件,处理后生成1个结果文件,最后n个结果文件可以merge成1个最终结果文件。
  
Software
  由于实验中的代码是由go语言实现的,所以需要先去看看go的基本语法以及相关教程,链接在这里Go(ps:需要翻墙/(ㄒoㄒ)/~~)
  使用git来下载实验的代码,repository为git://g.csail.mit.edu/6.824-golabs-2016。然后再去安装golang的编译器即可,这里实验中使用的是1.5版本。

Preamble: Getting familiar with the source
  mapreduce包提供了1个简单的Map/Reduce库的串行实现。正常应用应该调用Distributed函数[master.go]来启动1个任务,但是可以通过调用Sequential函数[master.go]来进行debug。
  mapreduce实现流程:
  1、应用提供一些输入文件,1个map函数,1个recude函数,reduce worker的数目(nReduce)。
  2、建立1个master节点,它启动1个RPC server(master_rpc.go),然后等待workers来注册(使用RPC call Register函数[master.go]). 当worker可用时(在第4、5步骤),schedule函数[schedule.go]决定如何分配任务到worker以及如何处理worker的failures。
  3、master节点认为每个输入文件对应1个map任务,为每个任务至少调用1次doMap函数[common_map.go]。每次调用doMap函数会读取合适的文件,并调用map函数来处理文件内容,为每个map文件生成nReduce个文件。
  4、master节点接下去为每个reduce任务至少调用1次doReduce函数[common_reduce.go]。doReduce函数收集nReduce个reduce文件,然后调用reduce函数处理这些文件,产生nReduce个结果文件。
  5、master节点调用mr.merge函数[master_splitmerge.go],来整合nReduce个结果文件成1个最终文件。
  6、master节点发送1个Shutdown的RPC调用到每个worker,来关闭它们的RPC server。

Part I: Map/Reduce input and output
  首先是实现Map/Reduce的串行执行,在给出的代码中缺少2个关键的片段:将map任务的输出分割成nReduce个文件的 doMap函数[common_map.go],以及将reduce任务的nReduce个输入整合成1个文件的doReduce函数[common_reduce.go]。
  为了帮助测试你的代码是否正确,实验中还提供了test文件[test_test.go]来测试。关于go test命令的说明可以看这里go test

go test -run Sequential mapreduce/... 

  run参数表示测试mapreduce文件夹下test_test.go文件中以Test开头包含Sequential的测试函数,即TestSequentialSingle和TestSequentialMany函数。这里针对TestSequentialSingle来分析一下具体流程,有助于编写doMap和doReduce函数。

func TestSequentialSingle(t *testing.T) {
    mr := Sequential("test", makeInputs(1), 1, MapFunc, ReduceFunc)
    mr.Wait()
    check(t, mr.files)
    checkWorker(t, mr.stats)
    cleanup(mr)
}
func Sequential(jobName string, files []string, nreduce int,
    mapF func(string, string) []KeyValue,
    reduceF func(string, []string) string,
) (mr *Master) {
    mr = newMaster("master")
    go mr.run(jobName, files, nreduce, func(phase jobPhase) {
        switch phase {
        case mapPhase:
            for i, f := range mr.files {
                doMap(mr.jobName, i, f, mr.nReduce, mapF)
            }
        case reducePhase:
            for i := 0; i < mr.nReduce; i++ {
                doReduce(mr.jobName, i, len(mr.files), reduceF)
            }
        }
    }, func() {
        mr.stats = []int{
  
  len(files) + nreduce}
    })
    return
}

  首先通过Sequential函数[master.go]来创建1个master结构体,然后运行1个goroutine来执行mr.run函数。其中master结构体的定义如下:

type Master struct {
    sync.Mutex

    address         string
    registerChannel chan string
    doneChannel     chan bool
    workers         []string // protected by the mutex

    // Per-task information
    jobName string   // Name of currently executing job
    files   []
MIT 6.824 课程的 Lab1 是关于 Map 的实现,这里单介绍一下实现过程。 MapReduce 是一种布式计算模型,它可以用来处理大规模数据集。MapReduce 的核心想是将数据划分为多个块,每个块都可以在不同的节点上并行处理,然后将结果合并在一起。 在 Lab1 中,我们需要实现 MapReduce 的基本功能,包括 Map 函数、Reduce 函数、分区函数、排序函数以及对作业的整体控制等。 首先,我们需要实现 Map 函数。Map 函数会读取输入文件,并将其解析成一系列键值对。对于每个键值对,Map 函数会将其传递给用户定义的 Map 函数,生成一些新的键值对。这些新的键值对会被分派到不同的 Reduce 任务中,进行进一步的处理。 接着,我们需要实现 Reduce 函数。Reduce 函数接收到所有具有相同键的键值对,并将它们合并成一个结果。Reduce 函数将结果写入输出文件。 然后,我们需要实现分区函数和排序函数。分区函数将 Map 函数生成的键值对映射到不同的 Reduce 任务中。排序函数将键值对按键进行排序,确保同一键的所有值都被传递给同一个 Reduce 任务。 最后,我们需要实现整个作业的控制逻辑。这包括读取输入文件、调用 Map 函数、分区、排序、调用 Reduce 函数以及写入输出文件。 Lab1 的实现可以使用 Go 语言、Python 或者其他编程语言。我们可以使用本地文件系统或者分布式文件系统(比如 HDFS)来存储输入和输出文件。 总体来说,Lab1 是一个比较简单的 MapReduce 实现,但它奠定了 MapReduce 的基础,为后续的 Lab 提供了良好的基础。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值