MIT 6.824 Lab3 2021 AB完成记录

说明

  • 在实验二的基础上,实验三整体来说还比较简单。同样的,这里只描述实验完成的整体思路和问题解决方法,只有代码骨架,不填充具体逻辑。实验二ABCD我之前也写过了。如果需要代码可以留言。

总体方法

总体架构

  • 我们首先要了解实现的整体架构是什么,关于这个,最好的展示就是网站中raft_diagram.pdf那张图。 一些核心的前提:KVServer(server.go) 是 State Machine, 每个KVServer对应一个Raft peer node, KVServer之间只通过Raft 服务来达成共识,不会直接交互。 根据paper Client interaction 的说明,KVServer应该指导请求来自哪个具体的客户端,且保存每个客户端的请求状态。即我们需要给每个客户端一个唯一的ID, 且其同一个请求需要有唯一的Seq, 两者结合来确定一个唯一性的请求。
  • 客户端的ID用 nrand()生成即可,测试最多7个客户端,不会重复,生产环境下会用IP:PORT的方法去定位具体的Client. 每个Clinet 维护一个lastRequestID, 来提供每一次请求的Seq.

一次请求的流程

在这里插入图片描述

  • 画了张图来描述它。
  1. Server(Leader)收到Client的Request
  2. 通过raft.Start() 提交Op给raft Leader, 然后开启特殊的Wait Channel 等待Raft 返回给自己这个Req结果。
  3. 底层共识达成后,Raft的所有peer会apply 这个Op, 每个Server会在单独的线程ApplyLoop 中等待不断到来的ApplyCh中的Op .
  4. 执行这个Op(GET全部执行,重复的PUT, APPEND不执行)
  5. Apply Loop 根据Op中的信息将执行结果返回给Wait Channel , 注意,只有Leader中才有Wait Channel 在等结果
  6. 返回执行结果给Request
  • 我们可以进一步总结这个过程,这个过程在Lab4中也能使用,Lab4扩展了Lab3中的Get, Put, Append操作。
    1. 在一个Loop里,全员监听一个指标,当这个指标发生变化时,会触发操作
    2. 只有Leader能够触发这个条件,follower不主动触发,等待被同步
    3. 条件被触发后,Leader判定条件是否准确,交由Raft特定的Op Log Entry; 根据需要设置WaitChan等待结果,同时设置Timeout
    4. Raft将Leader Op 同步给大家,ApplyEntry给上层每个Server
    5. Servers(包括Leader)读取Raft Apply Op 进行如下操作
      • Dupulication Detection
      • 执行Write,Update这种类型的操作,Read类型操作不执行
      • 判定Snapshot条件,满足,则SnapShot
      • 如果有WaitChan在等待,返回结果给WaitChan
    6. Leader通过WaitChan接受结果,执行Read类型操作,返回结果给Client. 或者Leader WaitChan超时,返回Client结果。

关于Server对Raft请求的超时问题

  • 有可能出现Server Start Command, 一直在等待的问题,其实超过一定时间,即说明Raft共识已经失败了。但无论是waitChan 还是labrpc中的Call方法,都没有“回调超时”的概念,会阻塞在哪里。
// Call() is guaranteed to return (perhaps after a delay) *except* if the
// handler function on the server side does not return.
  • 因此,我们已经手动为请求添加Timeout, 在Client 或者Server端都可以,请求发出后,如果超时没有回复,则认为 ErrWrongLeader, 并按逻辑重发即可

Duplicate Request的处理

  • 实验A的核心作用就是处理Duplicate Request . 保证重复的请求不会在状态机上被执行两边(同一ClientID:RequestID).
  • 这里的核心思想是KVServer来处理Duplicate 问题,而不是交由Raft来处理。对于我们收到的请求,无论是否重复,我们都提交给Raft作为它的log. 而KVServer 负责在接受apply log时判定这个log代指的Request Op是不是重复的,是重复的,我们就不在状态机上执行,直接返回OK即可(实际上GET无需考虑这个问题,因为他不会改变状态机的存储内容)。

关于Leader路由问题

  • 这里有一个可能坑人的地方,就是Clinet . servers[] 的序号和KVServers.me 不是 1 1对应的,而是随机shuffle过的。 但是KVServer.me 和 Raft.me 是对应的。 这就导致了Client 发送请求到一个不是LEADER的KVServer, 这个KVServer可以拿到raft.leader的序号并传回Client, 但Client 并不能通过client.servers[leaderNumber]来找到真正的Leader, 还是要随机访问另一个。
  • 因此提示里说的Server传回leader位置的优化做不到,除非你把这个随机的shuffle 慢慢学出来。所以说我们收到ErrWrongLeader时候,只要再随机访问另一个就行了。

关于Snapshot & Raftstate

  • 先说明概念:RateSate(currentTerm, voteFor, logEntries 和你要自己存储的状态)。 Snapshot (Server 维护的KeyValue数据库,其实就是内存中一个map, 和Server维护的关于每个Client Request的状态)。
    在这里插入图片描述

同样的,我们画图来理解这个流程
对于Leader这里:

  1. Raft Apply new LogEntries( CommandValid : true ), 这一举动说明RaftStateSize 在增加
  2. Leader执行操作,并根据RaftStateSize 和阈值maxraftestatesize判断是否需要命令Raft进行Snapshot
  3. 如果需要,则将自身的KVDB,RequestID等信息制作成snapshot, 并调用Leader Raft peer node 的 Snapshot () 接口
  4. Leader 安装Snapshot , 这分为三部分,修剪log Entries [] , SnapShot 通过Persister进行持久化存储, 在Appendentries中将本次的SnapShot信息发送给落后的Follower
  5. 返回执行结果给WaitChannel

对于Follower :
1 . InstallSnapshot 处理Leader的RPC请求,获取 snapshot数据, 裁剪log, 通过ApplyCh上报给Server (SnapshotValid: true)

2 . Applyloop 收到请求,调用CondInstallSnapshot() 来询问是否可以安装snapshot

3 . CondInstallSnapshot() 判定snapshot安装条件,持久化snapshot, 并通知Server可以InstallSnapshot

[这里说明一下,我的CondInstallSnapshot()直接返回了true, 因为我再InstallSnapshot RPC Handler中已经进行裁剪log, 如果CondaInstallSnapshot() 返回false, 则会造成Raftstate 和 snapshot的不一致 ; 其实我也没理解好这个CondInstallSnapshot()有什么用,至少在我的实现逻辑中,它并没有返回false的必要,求教求教]

和实验二的联系

  • 这里我的理解就是 【尽可能对Raft进行最少的修改】和 【即使通过实验二的测试,Raft也还是可能有问题】
  • 在实验二的基础上,我再实现实验三的时候没有对Raft有任何逻辑上的大改动,只不过排查出了一个小问题,即我把 lastApplied 也当作Raftstate 进行持久化了,导致所有Server一起restart 之后无法apply之前的所有log.

Skeleton Code

Client<

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值