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代码 + 问做过的人

这个我觉得真的应该找一伙有兴趣的人一起做,调不出来的及时交流,因为实在挑不出来的时候,你很可能踩坑了……

实现提示

  1. becomeCandidate 函数不应该包含发送 requestVote RPC 的工作
  2. appendEntriesResponse 的处理函数应该能够处理重复的回应(即使你的代码不会生成重复回应,测试数据中会有)
  3. RaftLogstorage 是用来提供 entries 的初始状态的
  4. (非标准行为) Leader 发现 commit 变化时必须立刻广播 appendEntries,而不能是 heartbeat
  5. Ready 中的 msg 应该在 apply commited entries 之后发出。如果在 apply 的过程中节点因为 ConfChange 停止了,也要在退出之前发出。

本文初稿完成于 2021/01/17,TinyKV 项目还在不断迭代完善,你阅读到本文时实际情况可能已与本文不同