完成了年初的flag Implement raft & raft based distributed kv store.

背景

放个图证明自己,爱过.

raft kvraft shardkv
https://blog.gaxxx.me/raft/raft_0.png https://blog.gaxxx.me/raft/raft_1.png https://blog.gaxxx.me/raft/raft_2.png

目标

学习6.824课程,以及相关的分布式知识,并且基于lab环境

  • 完成raft的分布式日志实现
  • 完成基于raft log的分布式kvstore

在踩坑的过程中,我碰到了这些问题或者有一些思考

  • 跑一次test的时候,没啥问题,但是跑十次可能错一两次
  • 碰到死锁怎么办,怎么处理不同的模块之间的锁
  • leader在正常工作时,有一个乱入的leader,发送了一个高term请求,如何快速recover
  • 用Raft怎么做zookeep或者kafka
  • 如何进行performance tuning
  • 如何scale

在实现过程中,我都有了一些看法,可以直接跳到最后部分。。。

准备

以下是每个test的实现,我会简单描叙

  • 要做的事情
  • 技术细节
  • 伪代码
  • 技术细节的实现

实现

raft

kvraft

shardkv

思考

  • 跑一次test的时候,没啥问题,但是跑十次可能错一两次
    • raft 细节处理
    • 出现偶然failure的情况一般都是persist的问题。 Raft paper里面对于commit的条件是,when the log replicate. 在处理heartbeat时,如果不存盘就返回,并且返回leader这个数据当前最新的log位置的话, leader可能就直接apply了。 这个时候如果发生crash, 就会出现问题。
    • 但是如果每次heartbeat有新数据需要存盘的话,可能会比较慢,尤其是对于arm主机来说。而且这是一个一次同时挂两台机器,才会出现的问题,所以实际操作中,有些实现是写到内存就返回的。
    • 还有一种方式是,异步存数据,但是下一个heartbeat再确认数据replicated, 这样正确性是OK的,但是过不了测试,因为慢。当然,如果实际系统里面,客户端对于latency 不敏感的话,是可以work的。
  • 碰到死锁怎么办,怎么处理不同的模块之间锁
    • 外部交互
    • 每个模块别把锁暴露给别人就可以了,理论上说加锁的scope是这样的 shardkv > kvraft > raft
  • leader在正常工作时,有一个乱入的leader,发送了一个高term请求,如何快速recover
  • 用Raft怎么实现zookeep或者kafka类似的功能
    • Raft的logid与zk的lastId很相似,写入时,我们可以与leader建立一个连接, 然后执行完之后拿到一个logid,记为write_id. 在Get的时候,我们可以与follower建立一个长连接,只要所有的Get请求的idx id比 write_id大,那不就妥了吗。。。
    • Kafka 集群,比如3个服务器,一台crash之后,其他server会起来take over, 3台服务器可以挂两个。 kafka的实现是因为它还挂了一个zk, raft也可以在前面挂一个shartctler对peer进行测试,如果3台挂了两台,shardctler可以增加一个新的group, 这个group里面只有一个活着的peer
  • 如何做performance tuning
    • 对于一个数据来说, commit的时间是

      • client —request—> leader
      • leader → persist
      • leader —heartbeat —> peer
      • peer → persist
      • peer —hearbeat reply → server

      如果为了提升性能, 可以

      1. persist用ssd或者用memory
      2. persist用异步来做,这样client latency会增加
      3. 减少网络latency, 减少peer的数量,peer之后可以接另外的raft group
  • 如何做scale
    • 如果写请求过多,可以做multi raft group
    • Get的请求可以放在follower里面,如果对于实时性要求不高的话
    • 可以使用多级的raft group,不同级别的raft group可以用不同的策略处理 OnMessage , 也可用不同的粒度来 Save Snapshot

参考 (据说贴得越多越专业)