TinyKV
TinyKV 是 PingCap TalentPlan 路径二的实现目标,产出是一个分布式kv数据库。GitHub仓库 给了一个模板和一些测试,把缺失的实现补上就做完了。
涉及
- 调库
- Raft
- KV 数据库
你可能会遇到
缺失文档和定义
TinyKV 存在大量的无注释变量、代码。当然作为代码完形填空题,不给一些注释也是题目的一部分。问题是它没有很好的说明每个函数或者变量的职责,测试接口又是直接调用用户实现函数的。实现又可以千奇百怪,比如 A 函数的一些工作 X 可以独立放到 B 里,也可以不放,但开发者按照 A 函数不做 X 工作来测试,就导致测试失败……最后还要靠读测试代码反推函数定义,或者反推变量的含义,这就很折磨。
实现不标准
TinyKV 内含的 Raft 算法并不是完全的按照论文实现。有些细节有出入但又没有说清。比如AppendEntries 和 HeartBeat 是分开的,这会出现很多细节上的差异。并且有些细节是论文中没有,有几种实现都是正确的,但做着做着发现由于测试接口只能选择其中一种。面向测试编程,折磨。
内存不足导致测试失败
我的笔记本是6代低压 i7 + 20G 内存。即便如此……也是跑不出来测试的。
make project2b
丧心病狂,一路吃到 12 GiB 内存 + 大量 IO TempFile。Linux 下 TempFile 在 /tmp
本来就吃内存,加上这个测试会内存泄露,20 G 内存的机器也跑不出来结果。如果手动把 TempFile 目录(kv/test_raftstore/cluster.go
文件中定义) 改到 SSD 上, 内存也是一样不够用。这种错误的表现是 top
显示内存用尽,测试程序突然终止,没有任何错误提示。
解决方案是手动运行各个测试,比如 project2b 中想单独运行 BasicTest2B,则可以运行 go test ./kv/test_raftstore -run BasicTest2B
。字符串”BasicTest2B”的位置是一个正则,比如 go test ./kv/test_raftstore -run Basic.*2B
效果相同。
如果你还要做
面向测试编程,调不出来的时候,看AC代码 + 问做过的人
这个我觉得真的应该找一伙有兴趣的人一起做,调不出来的及时交流,因为实在挑不出来的时候,你很可能踩坑了……
实现提示
becomeCandidate
函数不应该包含发送 requestVote RPC 的工作appendEntriesResponse
的处理函数应该能够处理重复的回应(即使你的代码不会生成重复回应,测试数据中会有)RaftLog
中storage
是用来提供entries
的初始状态的- (非标准行为) Leader 发现 commit 变化时必须立刻广播
appendEntries
,而不能是heartbeat
- Ready 中的 msg 应该在 apply commited entries 之后发出。如果在 apply 的过程中节点因为 ConfChange 停止了,也要在退出之前发出。
本文初稿完成于 2021/01/17,TinyKV 项目还在不断迭代完善,你阅读到本文时实际情况可能已与本文不同