MIT 6.824分布式 LAB4A:ShardCtrler

lab 4要求实现一个使用raft共识算法的分片存储系统。而在lab 4a中,我们仅需实现分片控制器的功能。

lab4中的分片存储系统有多个分片,这些数据分布在众多分片上,而每个分片都对应着一个集群组,可能一个集群组负责多个分片,一个集群组内的所有服务器都会使用raft共识算法进行状态的复制。

介绍

而本实验的重点为分片控制器,主要负责的工作是对集群组和分片之间关系的管理,我们仅需在/src/shardctrler文件夹中对client.go,server.go,common.go这三个文件进行修改即可。

go test

注意事项(实验教程中的Hint)

1、本实验的开始部分就如同kvraft的server那部分,可以直接借鉴照搬过来。

2、同样需要设计重复请求侦查机制,避免一条请求执行两遍造成错误。

3、分片控制器在有集群组的加入或者离开的情况下,由于分片负载平衡的需要,后续还要进行分片和集群组之间的再分配,确保分片均匀分配给这些集群组,以及尽量避免分片和集群组对应关系的变动。但是这个执行过程要求具有确定性的。因为分片控制器也使用了raft共识算法来进行冗余复制,Leader和follower各自在执行join,leave,move操作后,分片再分配后每个分片对应的集群组在每个backup上必须是相同的,因此要求这个执行过程具备确定性。而我们需要特别注意的就是,在Go里面map的遍历是不具有确定性的,每次遍历时,遍历的顺序都会发生变化。

4、Go中map数据类型是引用类型,因此如果想要进行深拷贝,需要避免通过赋值的方式,而是应该采取遍历的方式,将map中的key、value对一个个拷贝到新的map中。

5、-race同样可以帮你进行侦测数据竞争的问题,帮你找到bug。

本次实验内容

公共部分和客户端部分

1、设计重复请求侦查机制,加入id来标识每个rpc请求

服务端部分

1、完善ShardCtrler结构体

2、完善Op结构体

3、完善Join、Leave、Move、Query函数

4、设计executeThread函数

5、完善StartServers函数

代码阶段

公共部分和客户端部分

由于需要设计重复请求侦查机制,我们参考lab3中的设计方式,给每个请求都添加一个int64类型的id来标识。

因此,照搬lab3当时的方法,给common.go中每个Args结构体中添加一个int64类型Id,在client.go中每个请求操作的函数中,应当在rpc的args的结构体中给Id赋值。

代码如下所示,代码仅取部分展示,因为都是一样的,新增一条简单代码而已:

type JoinArgs struct {
    Servers map[int][]string // new GID -> servers mappings
    Id      int64
}

func (ck *Clerk) Query(num int) Config {
    args := &QueryArgs{}
    // Your code here.
    args.Num = num
    args.Id = nrand()
    for {
        // try each known server.
        for _, srv := range ck.servers {
            var reply QueryReply
            ok := srv.Call("ShardCtrler.Query", args, &reply)
            if ok && reply.WrongLeader == false {
                return reply.Config
            }
        }
        time.Sleep(100 * time.Millisecond)
    }
}

服务端部分

完善ShardCtrler结构体

由于lab4a和lab3做的事情十分相似。因此,照搬lab3中的设计。server需要等待共识完成后才能返回rpc调用结果给client,因此加入了条件变量。同时,重复请求侦查机制也是会将近期处理的请求的id记录下来,并将query的结果保存下来,因此新增了commandLog和configLog变量,分别用来记录近期处理的请求的id和近期的query请求的返回值。以上设计原理都和lab3一模一样。

type ShardCtrler struct {
    mu      sync.Mutex
    me      int
    rf      *raft.Raft
    applyCh chan raft.ApplyMsg

    // Your data here.
    cond       *sync.Cond
    commandLog []int64
    configLog  map[int64]Config
    configs    []Config // indexed by config num
}

完善Op结构体

Op结构体主要用于承载各个操作的信息,因此仅需把各个操作所需的信息打包到这个Op结构体中即可。

Server

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值