暂缓使用 Litestream 0.5.0
Litestream 是一款开源工具,可以实时将 SQLite 数据库备份到云存储。我很喜欢它,并在自己的所有项目中都使用它。
Litestream 归 Fly.io 所有,他们曾为了另一个名为 LiteFS 的替代项目而暂停了 Litestream 的开发近两年。两周前,Litestream 的创造者和首席开发者 Ben Johnson(本·约翰逊)宣布,他们已将重心转回 Litestream,并且刚刚发布了新版本 0.5.0。
我试用了 Litestream 0.5.0,但我提醒其他 Litestream 用户,在将其部署到生产环境之前,最好再等一个版本发布并进行更充分的测试。我迁移到新版本 Litestream 的过程并不顺利。
更新:Litestream 0.5.1 现已发布,修复了我遇到的大部分(但并非全部)问题。
更新 2(2025-10-17):Litestream 0.5.2 修复了我遇到的所有 bug,因此我计划将其部署到我的基于 SQLite 的应用中。
说明:我并不是在抱怨 Litestream。我很喜欢 Litestream,也很高兴看到它重新恢复开发。我只是希望让其他 Litestream 用户避免踩到我遇到的同样的 bug。
预期的迁移工作
从旧版本的 Litestream 升级到 v0.5.0 及以上版本,有两项有意为之的变更:
- 备份格式已更改,因此 Litestream 0.5.0 无法从旧版本 Litestream 创建的备份中恢复。
litestream.yml配置文件格式略有变化。以前有一个名为replicas的数组字段,但 0.5.0 将其改为了名为replica(单数)的字典。
Litestream 发布了一份实用的迁移指南,包含更多细节。
Litestream 0.5.0 的一个好处是现在有了官方 litestream Docker 镜像。(更正:读者 placardloop 指出这个 Docker 镜像并不是新出的,只是我一直没注意到。)以前我所有的 Docker 容器都需要大量样板代码来下载正确版本的 Litestream 并使其在容器中可用,但现在只需一行 Dockerfile:
COPY --from=litestream/litestream:0.5.0 /usr/local/bin/litestream /app/litestream我向 Litestream 0.5.0 的测试迁移
为了测试 Litestream 0.5.0,我尝试将其部署到我的项目 What Got Done 上。这是一个很好的测试对象,因为:
- 我已经宣布要关闭这项服务,所以用户已经停止使用该网站。
- 服务器一直因为 Litestream 0.3.13 中的一个 bug 而不断出错,该 bug 已在 0.5.0 中修复。
上传到 Backblaze 后端不再可用
迁移开始时,我先用 Litestream 0.3.13 下载了数据的最新副本,然后尝试使用 Litestream 0.5.0 以 Litestream 的新格式将其上传回 Backblaze 的云存储。但我遇到了这个错误:
error" db=store.db replica=s3 error="write ltx file: s3: upload to db/0000/0000000000000001-0000000000000001.ltx: operation error S3: PutObject, resolve auth scheme: resolve endpoint: endpoint rule error, Custom endpoint `s3.us-west-002.backblazeb2.com` was not a valid URI"同样的副本定义在之前的版本中一直有效,所以我有点困惑。
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
dbs:
- path: ${DB_PATH}
replica:
url: s3://${LITESTREAM_BUCKET}/db
endpoint: ${LITESTREAM_ENDPOINT}我尝试了几种指定 Backblaze S3 endpoint 的替代写法,但 Litestream 都把它们当作配置错误拒绝了,甚至还没开始尝试备份。我原来的配置是唯一被 Litestream 认可为有效配置的写法,但它却无法完成备份。
我提交了 Backblaze replica fails with “Custom endpoint … was not a valid URI” #789,Litestream 开发者 Cory LaNou(科里·拉努)第二天就修复了它。
既然我能够以 Litestream 的新格式将数据上传到 Backblaze 了,我就扫清了将 Litestream 0.5.0 集成到 What Got Done 中的障碍。
-if-replica-exists 消失了
我将 Litestream 0.5.0 部署到 What Got Done,但服务器启动失败,报出这个错误:
flag provided but not defined: -if-replica-exists我查看了命令文档,文档说 -if-replica-exists 仍然受支持:
$ litestream restore -help | grep if-replica-exists --after-context=1
-if-replica-exists
Returns exit code of 0 if no backups found.结果发现这个标志是被误删的,并且将在 0.5.1 中回归。
恢复失败,报 transaction not available
我没有因为 -if-replica-exists 的缺失而气馁,把它从我的启动脚本中删掉了。但随后我的服务器启动失败,出现了一个新错误:
level=ERROR msg="failed to run" error="cannot calc restore plan: transaction not available"这与 Litestream 的一个未关闭 issue 相符,其严重程度令人担忧:“CRITICAL - Complete Data Loss”(严重——完全数据丢失):
Litestream 不再创建目录
到了这一步,我愿意尝试任何办法来恢复运行,于是通过在我的 Docker 容器中从源码构建,运行了最新的前沿版本 Litestream。
幸运的是,最新版本绕过了我遇到的那个 transaction not available 问题,Litestream 在流程中走得更远了!
不幸的是,还有一个错误需要克服:
level=ERROR msg="failed to run" error="create temp database path: open /app/data/store.db.tmp: no such file or directory"这个错误其实很简单,我对发生的原因有相当大的把握。在旧版本的 Litestream 中,如果我让它把 SQLite 数据库恢复到 /app/data/store.db,而 /app/data 路径不存在,Litestream 会在写文件之前尝试创建该目录。
我查看了源码,发现这段代码流程中的文件夹创建逻辑消失了,但修复起来很简单,于是我提交了一个修复:
成功了!
应用了最终的 mkdir 修复的 我的 Litestream fork 让 What Got Done 恢复了运行!
反思
我用一个预发布 fork 让 Litestream 0.5.x 跑了起来,但我打算再等一两个版本发布,才会将其部署到我的其他项目中。0.5.0 的变更似乎比 Litestream 团队预期的更具破坏性,他们仍在与一些严重的 bug 搏斗:
- CRITICAL: Restore fails with ’nonsequential page numbers’ after checkpoint during Litestream downtime #752
- Local LTX Level 0 files are never compacted/removed #784
还有几个其他严重 bug 已在开发版本中修复,但尚未出现在生产发布中(更新:这些问题现已在 0.5.1 中修复):
- Restore does not update LTX ID information #781
- Age encryption configuration silently ignored in v0.5.0+ #790
- [Regression] LTX transactions get deleted in 0.5.0, cannot restore more than a few seconds #771
说明:再次强调,这不是对 Litestream 的批评。流式复制很难做对,他们所做的工作远比我能产出的要健壮。我感谢 Litestream 团队如此迅速地响应 bug 报告并修复问题。
随机一篇博客