2014年9月,我发布短文宣布 rqlite:在 SQLite 前加一层 Raft 日志,把每次写入复制到集群,使节点失效也不丢数据;源码同周末放到了 GitHub。据我所知,这是首个把 Raft 和 SQLite 结合的开源系统。如今“分布式 SQLite”已有十二个项目。我决定写下从 2014 年开始的全程版本,这一切我全程经历。2014 年的 rqlite 源于我在 jut.io 参与的集群系统,它需要少量关系型存储,却难定由哪个节点持有;用共识协议复制 SQLite 解决了它。
正文

2014 年 9 月,我发了一篇短文宣布 rqlite。想法很简单:把 SQLite 拿来,在它前面加一层 Raft 日志,把每次写入复制到集群里,这样丢掉一个节点也不等于丢掉数据。源码在同一个周末就放到了 GitHub。据我所知,那是第一个把 Raft 和 SQLite 结合起来的开源系统。当时没有别人在做,之后好几年也没有别人尝试。
如今“分布式 SQLite”已经成了一个类别,里面有十几个项目,少数拿到了风险投资,有两个被收购。现在写这个类别的人往往把故事从 2021 年左右讲起,所以我觉得应该把从 2014 年开始的这一版写下来。整个过程我都在场。
2014:rqlite
需求很具体。我在 jut.io 做过一个集群系统,需要少量关系型存储,但“该由哪个节点来存”这个问题没有好答案。用共识协议复制 SQLite 解决了它。工作中我们走了另一条路,但我继续做 rqlite,因为这个问题很通用,而解决方案很小。第一版用的是 goraft,也就是当时 InfluxDB 和 etcd 用的同一个库(大约在同一时期,我随后以核心开发者身份加入了 InfluxDB)。2016 年初,我把它换成了 Hashicorp 的 Raft 实现,rqlite 至今仍在用。
最重要的设计决定当时就定下来了,之后再没变过。rqlite 是一个 CP 系统。写入必须经过 leader,必须获得多数派确认,被分区隔离的少数派会拒绝写入。其他一切——HTTP API、读一致性级别、快照——都是由此派生出来的。
2014 年之前及同期
为了说实话,有两件事值得提。Expensify 多年来一直在自己的基础设施里用类 Paxos 协议复制 SQLite,并在 2016 年把它作为 Bedrock 发布。ActorDB 是一个 Erlang 系统,给每个“actor”一个由 Raft 复制的独立 SQLite 数据库,它出现的时间和 rqlite 差不多。两者在原生环境之外都没被广泛采用,但都说明这个想法当时已经浮出水面。rqlite 做的,是把它变成一个任何人都能运行的、独立的、通用开源东西。
2017:dqlite
Canonical 做 dqlite,是为了让 LXD 以及后来的 MicroK8s 得到一个嵌入式复制存储,而不必运行 etcd。Mark Shuttleworth 还真给我打过一次电话,我们聊过,希望 rqlite 能适配进去,但它始终不太合适。dqlite 最初用 Go 写,后来用 C 重写,并配了自己的 Raft 库。它是意图上最接近 rqlite 的项目,主要区别在于打包方式:dqlite 是你嵌入的库,rqlite 是你运行的服务。Canonical 需要的是产品内部的数据库,而我需要的是放在任何人产品旁边的数据库。
2021:Litestream 与思路转变
Ben Johnson(我在 InfluxDB 的同事)在 2021 年初发布了 Litestream。Litestream 完全不用共识。它监听 SQLite 的 WAL,把日志流式传到 S3,以几乎零成本的方式为单节点 SQLite 数据库提供灾难恢复。Ben 的观点是,大多数应用并不需要集群;它们只用一台机器,需要的是机器挂掉后能恢复的办法。对很多应用来说他是对的,接下来几年“SQLite 就够了”的潮流——那些博客文章和会议演讲——很大程度上要归功于这个论点。
Litestream 和 rqlite 回答的是不同问题。Litestream 问的是:机器挂了怎么办?rqlite 问的是:机器挂了,而且我不能等恢复怎么办?第一个问题更常见,第二个则是人们找到 rqlite 时心里的那个问题。
Fly.io 在 2022 年雇了 Ben,并推出了 LiteFS。LiteFS 在文件系统层面复制 SQLite,用来自 Consul 的租约来实现。这是第一次尝试把复制式 SQLite 变成平台功能,而不是让你自己部署的东西。最后还有个转折:Litestream 启发了 rqlite v8.0 处理 SQLite WAL 的方式。
2022:分叉与扩展
2022 年有两个项目走了 rqlite 和 Litestream 都没走过的路。cr-sqlite 以扩展形式给 SQLite 加上了 CRDT,让多个写入者可以在没有 leader 的情况下先分叉再合并。那是设计空间里的 AP 一角,适合 local-first 应用;在这类应用里,rqlite 的 CP 保证反而会碍事。
libSQL 直接分叉了 SQLite 本身。ChiselStrike(后来成为 Turso)想改引擎内部的一些东西;而 SQLite 项目不接受外部贡献,也不会去改这些东西。在这个分叉之上,他们做了一个带边缘副本的托管服务。Turso 靠这个拿到了风险投资,2026 年被 Supabase 收购。
大约在同一时期,SQLite Cloud 出现了,提供用 Raft 复制的托管 SQLite。它是包裹在云服务里、最接近 rqlite 原始设计的项目。
2022 年以后:平台
Cloudflare 在 2022 年发布了 D1,把 SQLite 作为其边缘网络里的 Serverless 数据库,后来又把 SQLite 存储放进了 Durable Objects。这是把复制式 SQLite 当作托管产品来卖,而这家公司并不需要告诉你它是怎么工作的。Turso 的服务也是同一种形态。这个类别已经从“你运行的东西”变成了“你购买的东西”。
这十二年说明了什么
我想有三点。
核心是对的。把 SQLite 当作存储引擎、把复制加在外面,这种思路已经被至少八个团队用不同的需求和不同的协议重新发明了一遍。没有人找到理由停止这么做。
设计空间有三个角,而且它们是按顺序出现的。先是共识(rqlite、dqlite):一个 leader,强一致性,一个集群。其次是流式(Litestream):一个写入者,廉价的恢复,没有集群。第三是合并(cr-sqlite,以及 local-first 潮流的一部分):多个写入者,最终一致性。每一种都对应不同的问题,而多数争论其实是各自用户在争“到底问的是哪个问题”。
钱流向了平台。rqlite、dqlite 和 Litestream 都是开源且免费的。那些融到资或被收购的项目,是把复制式 SQLite 变成了带账单的服务。基础设施想法通常都是这个命运,我并不介意。但值得记下一笔:这个想法在有人拿它卖钱之前,已经开源了八年。
rqlite 还在。它做的还是 2014 年那件事,只是做得好很多;当你想要一个可以自己运行、完全理解、而且不用付钱给任何人的容错关系型数据库时,它仍然是你会选的那个东西。十二年过去,我对自己在这个故事里的位置感到满足。
评论
讨论围绕分布式 SQLite 的落地选型展开,气氛以务实追问和求助推荐为主,并夹杂一点对作者自我标榜的调侃。分歧主轴是 dqlite、rqlite、D1 等方案在生产中的可靠性与易用性,以及社区是否需要一个同时具备嵌入式、集群、独立节点和 S3 备份等能力的集大成项目。
认为 D1 在生产中不可靠,应优先使用 Durable Objects
- 有开发者在生产中使用 D1,认为其可靠性不足;并引述 D1 开发者的说法,指出 D1 只是在 Durable Objects 之上包装出的 SQLite 接口,即便只需要一个全局数据库,也应实现为单例 Durable Object 而不是用 D1(高赞)。 > 几乎总是应该直接使用 Durable Objects 存储,因为 D1 只是把单例 Durable Object 包装成 SQLite 接口。(@piterrro)
求更健壮的替代方案并追问基准与并发用法
- 有人正在小规模集群中使用 dqlite,但打算迁移到更健壮的方案,并直接询问该规模下的推荐;也有人认为分布式 SQLite 想法虽好,但缺少基准测试和优势场景,还有人不理解最新 Rails 将 SQLite 列为生产选项时如何处理并发访问,整体反映出对可验证性能与生产落地方式的关注(较多人)。 > 分布式 SQLite 的想法不错,但有没有基准测试,它在哪些用例里有优势?(@a3nz3g)
认为 rqlite 比多数集群数据库架构更易上手
- 有人此前并未细究,但初看认为该项目比绝大多数集群数据库架构都更容易,并把 rqlite 作为可考察的替代方案提出来(少数人)。 > 它看起来比绝大多数集群数据库架构都要容易得多。(@chasil)
希望有项目同时满足嵌入式、集群、独立节点与 S3 备份
- 有人列出理想清单,希望出现同时具备 SQLite 式嵌入式、dqlite 式集群、rqlite 式独立节点、litestream 式 S3 备份,以及可像 cr-sqlite 那样在 CP 之外可选 AP 的项目,反映出对现有方案碎片化的不满(少数人)。 > 有没有项目能把嵌入式、集群、独立节点、S3 备份和可选的 AP 能力都合到一起?(@Kinrany)
调侃作者在结尾刻意强调蓝图署名
- 有人表示文章读着有趣,但到结尾作者刻意确保历史记录下“谁画的蓝图”,以此调侃作者的自我标榜,代表了一种轻松的社区情绪(少数人)。 > 读着挺有意思,直到结尾作者非要确保历史记住是谁画的这张蓝图。(@brooksbp)
有价值的补充
- SQLite 官方还有 hctree 这一相关项目,评论里作为分布式 SQLite 的补充选项被提到(@feverzsj)。