一个开源数据库项目,居然要把SQLite内置的日志机制完全接管过来。rqlite 10.0版本最近发布,核心改动就藏在这个看似反直觉的设计里。
rqlite的定位很明确:轻量级、开源、具备容错能力的关系型数据库,底层用SQLite存储,用Raft协议做分布式一致性。但SQLite原生的WAL(预写日志)工作方式,和rqlite的需求存在根本冲突。
![]()
SQLite自己管理WAL时,会在日志膨胀到一定程度自动checkpoint,或者在最后一个连接关闭时触发。这些时机对单机数据库没问题,但对rqlite是灾难——因为rqlite把WAL当成了增量状态追踪的核心载体,一旦SQLite擅自checkpoint,这份"增量快照"就失效了。
问题的根源在Raft的设计。Raft只干一件事:维护一份状态机变更日志,并确保它在集群各节点完全一致。为了防止日志无限增长,Raft需要定期做snapshot:把当前状态机完整拷贝到磁盘,然后删除已被snapshot覆盖的日志条目。
rqlite早期用的就是HashiCorp Raft库默认的snapshot方案:Raft要snapshot时,直接拷贝整个SQLite数据库文件。2GB的数据库,哪怕只改了几百行,也要完整复制2GB。部署规模上到多GB级别后,这个方案彻底跑不动了。
![]()
WAL模式给了rqlite出路。SQLite在WAL模式下,所有修改先写成"帧"(frame),每帧对应一个被改动的数据页。checkpoint之前,WAL里精确保存着自上次checkpoint以来的全部变更。
rqlite的新方案很直接:Raft请求snapshot时,rqlite先复制当前WAL交给Raft,然后自己触发checkpoint把WAL刷回主数据库。WAL清空,重新开始累积下一批变更。任何时候,WAL内容就是"相对于最后一次Raft snapshot的未提交状态"。
这样snapshot的代价从"全量拷贝数据库"降到"拷贝WAL文件",通常只有几十MB甚至更小。代价是rqlite必须完全掌控checkpoint时机——SQLite不能再自作主张。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.