「不要文件系统,也不要 malloc」:TigerBeetle 的性能工程有多偏执

| | 2 次浏览

8 月 21 日,一篇题为《TigerBeetle Core System Architecture: Deconstructing Performance Engineering》的第三方架构解析登上了 Hacker News,把一款小众数据库再次推到聚光灯下。TigerBeetle 是一个用 Zig 编写、面向金融记账场景的开源数据库,在中文技术圈存在感不算强,但每次被讨论,话题几乎都绕不开同一个字:怪。它不用操作系统的文件系统,不在运行时分配内存,甚至不用主流的 Raft 共识协议。这篇长文做的,就是把这些"怪"逐条拆开,还原背后的性能工程逻辑。

一份反常识的设计清单

大多数数据库的演进史是一部"加法史":加缓存、加线程池、加可插拔存储引擎。TigerBeetle 走的是彻底的减法路线:

  • 绕过文件系统。 它直接对块设备读写:Linux 上走 io_uring,Windows 上走 IOCP。页缓存、写放大、文件系统自身的延迟抖动,在它眼里都是不可控变量,于是干脆自己管理磁盘布局。
  • 没有 WAL。 传统数据库"先写日志、再写数据页"的双写路径被整个砍掉——副本之间复制的 append-only 消息日志,本身就是数据库本体。
  • 运行时零 malloc。 所有内存在启动时一次性静态分配。没有碎片问题,没有分配器带来的隐形停顿,尾延迟因此变得可预测。
  • 一切皆批处理。 网络消息固定按 1MB 一批,磁盘 IO 与请求执行同样成批进行,把每次系统调用的固定成本摊到极薄。
  • VOPR 代替 Raft。 共识层选用 1988 年提出的 Viewstamped Replication:一种主备式复制协议,配合 4~6 副本的 mesh 复制拓扑,避开了领导者选举等一整类复杂度。

单看每一条,都像是工程上的"洁癖";合在一起,它们其实服务于同一个目标。

真正的底牌是确定性

如果说上述取舍是"术",确定性才是"道"。TigerBeetle 强制要求:相同的输入序列,必然产生相同的输出——包括相同的故障恢复路径。这带来一项竞争对手很难复制的能力:确定性模拟测试。团队在 CI 中用虚拟时钟、虚拟磁盘与虚拟网络,注入坏块、丢包、时钟漂移等故障组合,每天"排练"成千上万种灾难场景。换句话说,它对极端情况的信心不是在线上撞出来的,而是靠可复现的模拟一层层堆出来的。

背景与影响:这些取舍为什么成立

金融记账场景的画像很明确:写入密集、单条记录极小、对一致性和可预测吞吐的要求高于对单条延迟的要求。这解释了 TigerBeetle 的激进——官方基准测试中单节点每秒可处理百万笔量级的转账,后续跨集群测试更把吞吐推到每秒数千万笔。而"消息日志即数据库"的设计,也让它在副本一致性上天然比"日志+数据页"双路径的架构少了一类状态分裂的麻烦。

代价同样真实:这套系统对部署环境的要求苛刻(独占块设备),运维心智模型与主流云原生生态并不合拍,通用查询能力也远不及 Postgres 一类的全功能数据库。它更像一把为特定场景锻打的手工刀,而非瑞士军刀。

写在最后

对绝大多数业务开发者,照搬这套方案既不现实也不必要——你的服务大概率不需要绕过文件系统。但有两点值得带走:其一,尾延迟的敌人往往不是"算得不够快",而是路径上的不可控环节,性能工程的第一步是把不可控变成可控;其二,确定性的价值长期被低估,任何能让 bug 变成百分之百可复现的设计,都会在调试与测试环节加倍返还。TigerBeetle 的意义未必在于被大规模部署,而在于它像一份摊开的施工图,让人看清在层层抽象之下,系统这门手艺还能做到什么程度。

评论(0)

暂无评论,来写第一条吧。