数据库世界里一直有一道很具体的夹层问题。左边是原生 SQLite:简单、可移植、顺手,直到“机器坏一台也得继续跑”这件事突然变成硬要求。右边是完整的分布式 SQL 系统:能力强、韧性足,同时也常常带来更重的运维与认知负担。rqlite 在 2026 年仍值得单独介绍,正因为它把自己牢牢放在这道夹层里。它拿 SQLite 那套文件式关系模型做底座,再用 Raft 把它包成一个可复制、可故障切换、通过 HTTP 访问的集群,面向的是那些需要高可用 SQL 状态、又不想把数据库本身养成一整套平台的团队。[1][2][3]
这条承诺之所以值得认真看,不只因为概念顺耳。截至 2026-04-24T06:33:25Z UTC,GitHub API 显示 rqlite/rqlite 仓库有 17,438 stars、773 forks、83 个 open issues,最近一次 push 时间是 2026-04-21T10:33:37Z。[7] 最新稳定版是 v9.4.5,发布时间为 2026-03-10。[8] 这些数字当然不能替代架构判断,却足以说明,这并非一套停留在 demo 感的系统。官方设计文档把项目历史写得很直白:自 2014 年起,rqlite 一直在持续调整共识层、API、节点发现模型与重启恢复路径。[3]
配图说明:题图没有放集群拓扑图,也没有放控制台截图,而是用了 Philip O'Toole 的 GitHub 肖像。这种选择很合适,因为本文写的是一篇项目导读,重点落在系统边界与作者路径上。rqlite 到今天仍像一套创始人气质很强的数据库:小、清楚、克制,而且始终围着 SQLite 与 Raft 这两条主线展开。[9]
rqlite 真正优化的对象是什么
把 rqlite 简单说成“分布式 SQLite”,方向没错,力度却还不够。更有用的说法是:它是一套给“重要但规模不大的关系型状态”准备的 SQLite 集群方案。官方 features 页讲得很直接:rqlite 的目标是高可用、容错、关系型数据,同时把部署与运维压低到单二进制、少配置、几秒可起的程度,所有写入都通过 Raft 复制。[1]
这句话里最重要的部分,其实并非“高可用”,而是那句没有被藏起来的限制。官方文档明确写着,rqlite 优先考虑一致性与可用性,而并非写吞吐,因为每一次写入都要经过 Raft 日志。[1] 这就是判断它是否适合自己的第一道边界。若你的问题是“这份 SQL 状态不大,但不能随着一台主机一起倒”,rqlite 会显得很漂亮。若你的问题是“我们需要很多并行写入者,或者非常高的写入吞吐”,那它的核心设计已经把答案交代出来了。[1][3]
它的接口形态也因此显得很清楚。每个节点都暴露 HTTP 端点,分别处理写请求、读请求,以及统一的请求入口,客户端用 JSON 就能直接访问数据库,不需要额外的私有协议。[2] 参数化语句、一次请求里多条语句的原子执行、请求级事务控制,都已经放在文档与 API 里。[2] 这背后体现的是很鲜明的产品判断。rqlite 不只是要把 SQLite 复制出去,它还想把“被复制后的数据库应该如何被工程团队接入”这件事,压缩成一套足够轻、足够清楚的交互面。
真正的代价,集中在写路径上
理解 rqlite,最需要诚实面对的地方也在这里。只有当“维持更重数据库平台的成本”大于“为每次写入支付 Raft 成本”时,rqlite 才显得划算;反过来,这笔账就会掉头。官方设计文档说得很明白:Raft 日志是所有已提交 SQLite 命令的权威记录,所有节点都按同样顺序重放这些条目,因此每个节点上的 SQLite 数据库才能收敛成同一个状态。[3] 这给了系统非常干净的心智模型,也决定了写路径必然是整个系统的重心。
项目确实提供了一些性能缓冲区,但这些缓冲区本身也写得很坦白。Queued Writes 允许客户端更快返回,请求会先进入本地写队列,随后再批量写入并持久化;可文档同样强调,HTTP 200 OK 在队列模式下只表示请求已经成功入队,并不表示数据已经进入 Raft 日志,若节点在这段窗口里崩溃,就存在数据丢失风险。[6] 这并非一个“不要用”的信号,而是一个“要按原义来读”的信号。rqlite 的性能选项并没有取消一致性模型,它只是允许你在应用可以承受的时候,明确地向外挪一步。[6]
读取这一侧,产品形态反而更灵活
许多人第一次看 rqlite,会先被写路径的约束吓到,却忽略了读侧其实更有层次。rqlite 提供 weak、linearizable、none、auto 与 strong 几种读一致性模式;官方文档几乎把建议写成了默认答案:大多数应用直接用 weak,生产环境尽量不要用 strong,因为它代价更高,却没有比 linearizable 带来更实际的收益。[4] 这套层级关系很说明问题。rqlite 对读取的默认理解,并非“每次查询都要上最重的共识礼仪”,而是“足够快、足够新、并且对 Leader 状态有清楚认识”。
这件事在 read-only nodes 上尤其明显。clustering 文档写道,read-only nodes 可以承担大流量查询,或者放在网络边缘,把一份数据库副本放到更接近用户的位置,同时又不参与 quorum 与 Leader 选举。[5] 它们照样接收 Leader 的写入流,并把这些写入应用到自己的本地 SQLite 数据库上;即便与核心节点之间短暂断链,也能继续在本地服务查询,只不过数据有或许陈旧。[5] 这条边界非常适合很多真实工作负载。你可以把投票节点看成持久化核心,再把 read-only nodes 当成一层廉价的读取扩展面,把配置数据、引用数据、应用元数据推到更靠近消费端的位置。
更重要的是,文档没有把这里写成空泛的“弹性扩容”。若你访问 read-only node 时没有显式使用 none 或 auto,该节点会把请求转发给 Leader,于是所谓本地读取就被抵消了。[4][5] freshness 这类参数也同样保持克制:它能帮助你限制节点脱离 Leader 的时长上界,却不会神奇地替你承诺“结果一定是最新”,除非你再接受更严格的检查方式与随之而来的运维要求。[4] 这是 rqlite 作为 OSS 项目特别可贵的一点。它的文档一直在说明:哪些能力存在,哪些推论并不能顺手成立。
备份与恢复并非附属功能,而是整套主张的一部分
rqlite 读起来更自然手的另一层原因,在于它把大量精力放在 backup 与 restore 上。官方推荐的备份路径,是通过 shell 或 /db/backup API 直接拿到底层 SQLite 数据库副本,同时支持 SQL dump、压缩备份、VACUUM 后备份,以及围绕 Leader 的备份行为控制。[5] 自动备份可以按周期推送到 S3、兼容 S3 的对象存储、Google Cloud Storage 或本地文件系统,而执行这件事的永远只有 Leader。[5]
这并非简单的“功能做全了”。它构成了 rqlite 整体论点的一部分。恢复路径仍然围绕熟悉的 SQLite 工件组织,而并非逼你接受一套完全陌生的专用格式。系统支持把单个节点直接从 SQLite 数据库镜像里 boot 起来,以便在灾难恢复或大数据集初始化时更快完成上线;也支持把节点或集群从 SQLite 文件或 SQL 文本 dump 里 load 进去,在便利性优先时完成恢复。[5] 从另一层看,rqlite 的高可用,并非建立在“把 SQLite 的可携带性全部抛掉”之上。它更像是在说:线上运行时用集群守住可用性,出故障时仍然让你回到熟悉的 SQLite 物件上。
它最适合落在哪类团队手里
来自外部操作者的信号,也恰好印证了这种定位。Replicated 在介绍 App Manager 用 rqlite 取代 Postgres 时,把这次变化写成一条朝着“更高可用、也更易支持”的应用元数据存储路径迈出的步骤。[10] 这正是 rqlite 最顺手的那类工作负载:并非永不停息的重写事务主库,而是那种必须共享、必须关系化、必须在节点故障后继续可读可写的重要状态。
因此,真正值得问的问题,并非“我们喜不喜欢 SQLite”。更准确的问题是:我们的 SQL 状态是否规模适中却又足够重要,我们是否真在乎单二进制、低摩擦的运维表面,以及我们是否愿意为这种简单性支付单 Leader、Raft 驱动的写路径成本。[1][2][3] 如果答案是肯定的,rqlite 依然是开源世界里很清楚的一条中间道路,站在嵌入式数据库的轻便感与完整分布式数据库的沉重度之间。若答案是否定的,它自己的文档往往会先把原因讲清楚,而不用等到生产环境来代替说明。[1][4][6]
来源
- rqlite 文档《Features and Use Cases》—— 项目定位、单二进制运维、基于 Raft 的复制、自动备份、read-only nodes,以及“优先一致性与可用性而并非写吞吐”这条边界。
- rqlite 文档《Accessing rqlite》——
/db/execute、/db/query、/db/request、参数化语句、请求级事务,以及基于 HTTP/JSON 的接入模型。 - rqlite 文档《Design and implementation》—— 项目演进历史、Raft 日志的权威性、日志压缩、SQLite WAL 模式,以及集群设计细节。
- rqlite 文档《Read Consistency》——
weak、linearizable、none、auto与strong的语义,以及freshness、freshness_strict的工作方式。 - rqlite 文档《Backup and Restore》—— 热备份、
/db/backup、自动备份目标,以及基于 SQLite 数据的 boot/load 恢复路径。 - rqlite 文档《Queued Writes》—— 异步批量写入、sequence number、队列刷新,以及写入进入 Raft 日志前的耐久性边界。
- GitHub API,
rqlite/rqlite仓库快照 —— 写作时的仓库描述、stars、forks、open issues 与最近 push 时间。 - GitHub releases,
rqlite/rqlite—— 最新稳定版v9.4.5与公开发布节奏。 - Philip O'Toole 的 GitHub 个人页 —— 本文题图所用肖像的来源页面。
- Replicated 博客《Enhancing the Replicated App Manager with Rqlite》—— 来自操作者一侧的案例,说明 rqlite 如何承接高可用的应用元数据存储。