设为首页 加入收藏

TOP

MIT-6.824 Lab 3: Fault-tolerant Key/Value Service(二)
2019-09-17 18:52:30 】 浏览:60
Tags:MIT-6.824 Lab Fault-tolerant Key/Value Service
求的序列号seq和对应的响应结果,根据这个信息可知,当再次收到这个客户端的序列号小于seq的请求时,说明已经执行过了,直接返回结果。

如果之前没有执行过,那么调用

kv.rf.Start(command)

将Log Entry提交给raft,并且阻塞等待raft将这个Entry拷贝到其它大部分server,从阻塞返回后,说明这个Entry已经被拷贝到大部分server了,并且已经执行了命令,这时可以将结果返回给Clerk了。

那么在哪里接收raft的消息呢?KVServer在创建的时候会在一个线程中执行如下函数:

func (kv *KVServer) applyDaemon()  {
    for appliedEntry := range kv.applyCh {
        command := appliedEntry.Command.(Op)

        // 执行命令, 过滤已经执行过得命令
        kv.mu.Lock()
        if latestReply, ok := kv.latestReplies[command.Cid]; !ok || command.Seq > latestReply.Seq {
            switch command.Operation {
            case "Get":
                latestReply := LatestReply{Seq:command.Seq,}
                reply := GetReply{}
                if value, ok := kv.db[command.Key]; ok {
                    reply.Value = value
                } else {
                    reply.Err = ErrNoKey
                }
                latestReply.Reply = reply
                kv.latestReplies[command.Cid] = &latestReply
            case "Put":
                kv.db[command.Key] = command.Value
                latestReply := LatestReply{Seq:command.Seq}
                kv.latestReplies[command.Cid] = &latestReply
            case "Append":
                kv.db[command.Key] += command.Value
                latestReply := LatestReply{Seq:command.Seq}
                kv.latestReplies[command.Cid] = &latestReply
            default:
                panic("invalid command operation")
            }
        }

        DPrintf("%d applied index:%d, cmd:%v\n", kv.me, appliedEntry.CommandIndex, command)

        // 通知
        if ch, ok := kv.notify[appliedEntry.CommandIndex]; ok && ch != nil {
            DPrintf("%d notify index %d\n",kv.me, appliedEntry.CommandIndex)
            close(ch)
            delete(kv.notify, appliedEntry.CommandIndex)
        }
        kv.mu.Unlock()
    }
}

kv.applyCh这个chanel会在创建raft的时候传给raft,当某个Log Entry可以被commit的时候,raft会往这个chanel中塞,只要for循环这个kv.applyCh,就能知道已经被commit的Entry,拿到Entry后,根据其中的命令执行相应的操作,然后通知KVServer.Get()继续执行。

具体代码在:https://github.com/gatsbyd/mit_6.824_2018
如有错误,欢迎指正:
15313676365

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇MongoDB数据库(二):增删查改 下一篇数据库:MySQL实战;左链接;查询..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目