2021MIT6.824 Lab3总结:KVRaft

代码地址

https://github.com/c-toast/6.824-golabs-2021

基础概念

在lab2的raft上实现分布式key-value存储服务,该服务需要具备线性性质。所谓线性性质,就是存在一个根据请求的发起时间和回应时间进行排序的请求序列,使得该序列中的读请求能读到上一个写请求后的结果。

MIT6.824 lab3 实现细节

该实验看起来难度不是很大,但做之前需要提前想清楚可能的corner case,并针对这些corner case设计相应的解决方案,才能通过lab的测试。实验中涉及到client和server以及server和raft层的交互,在考虑corner case的时候要枚举交互过程中所有可能因为网络原因、硬件宕机导致的情况。corner case包括:

  1. client发送相同的请求给同一server或不同server。
  2. client收不到回复而再次发送已被server执行的请求。
  3. raft旧leader的日志被新leader的日志覆盖导致请求未被commit。
  4. raft层提供了乱序或旧的commit日志

针对这些corner case,一些细节和注意点如下:

  1. 用clientID+reqSeq来标识请求,便于重复检测。
  2. 不应该在client和server的交互过程中进行重复检测,而应该在server和raft的交互过程中进行重复检测。也就是说,client可以发送多个相同的请求给server,然后server可以将这些重复的请求都交给raft排序,当raft返回结果之后,server再进行重复检测,对于重复的请求,server只执行一遍(幂等性)。这是因为server和server之间无法进行可靠一致的交流,因而server无法知道其他server是否收到了重复的请求,所以在client和server的交互过程中进行重复检测是及其困难的。但是raft层可以提供在raft节点间具备一致性的结果,因而server只要根据raft提供的结果即可实现重复检测。
  3. 当server执行完一个请求后,需要将请求缓存起来,这样当client由于网络原因未收到执行结果而再次发送重复的已执行请求时,server可以从cache中取出执行的结果,返回给client。这里只要缓存client的最新(即拥有最大reqtSeq)的已执行请求即可。
  4. 当raft中的日志项被覆盖而导致不能commit时,server要返回失败给client。建议使用超时失败机制。当过了一定时间之后请求仍然未被commit,server则返回失败给client。虽然这样做的话可能会出现请求被commit并执行了,server仍然返回失败的情况,但由于server会cache执行结果,因而当客户端重发请求时,最终依然会收到服务端cache的执行结果。
  5. 在实现过程中需要判断server交给raft层的请求有没有被覆盖。可以对比server传给raft的请求和raft返回给server的请求是否相同。但更简单直接的方式是看任期。如果server传递请求给raft leader的时侯 leader的任期和raft commit请求时候的任期相同,则可以判断请求没有被覆盖。(因为raft规定了leader不会覆盖自己的日志)
  6. snapshot中,要存储kv表,cache,每个client的reqSeq。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值