Kvraft 实现
November 10, 2021
6.824 Lab 3: Paxos-based Key/Value Service (mit.edu)
在kvraft这个系统里面,主要是处理 GET / PUT / APPEND的请求,要通过的测试,对于这些请求有如下的约束
- 客户端是一个一个发送请求的
- 对于客户端的 PUT / APPEND 可能会出现网络错误,无法到达服务端,也可能多次到达服务端,服务器应该能保证exactly once.
目标
- 完成所有的Test
完成所有的Test
- 第一步,完成TestBasic3A, 这个测试里面,每个client写不同的key,然后多次迭代,看看每次写入和读取的是否一致。
- 在Snap的时候,把所有的状态就写进去就可以了。
细节
- 对于server端来说,如何存储key / value。
- 对于Get请求,需要把它放到log里面处理吗
- 如果把所有的请求都通过Start放入到Log里面, 什么时候apply,apply之后怎么返回。
伪代码
// 客户端代码
while not_complete:
select_peer
rpc_call_cmd()
if errcode == ErrWrongLeader / ErrTimeout:
continue
return result
// 服务器代码
cmd = get_a_cmd()
start(cmd)
......
wait cmd
......
if is_timeout:
return ErrTimeout
return cmd.result
细节处理
- 所有的请求,都需要放到logs里面,然后在apply的时候处理. Apply的时候,因为是在单独的线程,如果其实 key / value 直接用map就行。
- 对于Put 和 Append请求,我们需要为每个client配置一个incremental seq id, 然后在服务端处理的时候保证,对于同一个client id, seq id 是递增的,在这个case里面,应该是每次都是喜加一。
- 对于已经执行过的PUT / APPEND 请求 (seq id比当前的小), 可以直接返回成功。
- 在服务器端维护一个 (log_idx, log_term) → (chan result) 的map, apply处理结束之后,给chan result发送消息,然后结束该rpc
- 可以把 (client_id , seq_id) 的逻辑封装在内部,对外只暴露 OnMessage / OnSnapshot 的接口。
总结
kvraft里面主要增加了状态处理完成之后,给客户端应答的工作。如果客户端是一个长链接,可以异步的返回处理结果,这个就跟zk比较类似了。