litestream 把 SQLite 实时复制到 S3 / Backblaze(秒级 RPO 备份)

起因

我们的小型生产服务用 SQLite(部署简单 + 性能够 + 单文件备份)。
但默认备份方案最多每天 cron sqlite3 .backup + scp 异地。两次备份之间
有 24 小时 RPO(最坏丢一天数据)。

litestream 是开源工具,把 SQLite 的 WAL 日志实时增量复制到 S3 兼容
存储。RPO 降到秒级,无需改 application 代码。

解决方案

# 二进制安装
LITESTREAM_VERSION=0.3.13
curl -fsSL https://github.com/benbjohnson/litestream/releases/download/v${LITESTREAM_VERSION}/litestream-v${LITESTREAM_VERSION}-linux-amd64.tar.gz \
  | sudo tar xz -C /usr/local/bin litestream

litestream version

或 Docker:docker run litestream/litestream

配置

/etc/litestream.yml

dbs:
  - path: /srv/knowledge/db.sqlite3
    replicas:
      - type: s3
        bucket: my-backups
        path: knowledge
        endpoint: https://s3.us-east-005.backblazeb2.com
        region: us-east-005
        access-key-id: ${B2_KEY_ID}
        secret-access-key: ${B2_APP_KEY}
        retention: 720h           # 保留 30 天
        snapshot-interval: 24h    # 每天全量 snapshot

litestream 工作原理:

  1. application 写 db.sqlite3 → SQLite 写 WAL
  2. litestream 后台读 WAL 增量帧
  3. 每个 WAL 帧立刻上传到 S3(默认 10s 内)
  4. 定期(默认 24h)做一次全量 snapshot
  5. retention 期外的 snapshot + WAL 自动清理

systemd service

# /etc/systemd/system/litestream.service
[Unit]
Description=Litestream
Requires=network.target
After=network.target

[Service]
User=trio
Group=trio
EnvironmentFile=/etc/litestream.env
ExecStart=/usr/local/bin/litestream replicate -config /etc/litestream.yml
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

/etc/litestream.env

B2_KEY_ID=00abc...
B2_APP_KEY=K00...
sudo systemctl enable --now litestream
journalctl -u litestream -f
# 看到 "replicating wal frames..."

验证副本

litestream snapshots /srv/knowledge/db.sqlite3
# replica  generation       index  size       created
# s3      abc123             5     12345678   2026-05-24T03:30:00Z

litestream wal /srv/knowledge/db.sqlite3 | head
# replica  generation  index  offset  size

灾难还原

服务器全没了,新机器恢复:

# 装 litestream + 复制 /etc/litestream.yml + .env 到新机器
litestream restore -o /srv/knowledge/db.sqlite3 \
  s3://my-backups/knowledge
# 从最新 snapshot + 重放 WAL 到最新状态
# 几秒-几分钟(取决数据量)

# 启动 application
sudo systemctl start knowledge

时间点恢复:

litestream restore -timestamp 2026-05-20T10:00:00Z \
  -o /tmp/db-at-may-20.sqlite3 \
  s3://my-backups/knowledge

恢复到任意 30 天内的时间点。

效果

  • RPO 从 24h → 10s
  • 灾难还原 = 一行 litestream restore
  • B2 存储费用:30 天保留 ~2 GB DB 约 $0.10/月
  • application 零改动:litestream 在后台独立进程跑

与其它方案对比

cron .backup + scp litestream PG streaming replica
RPO 24h ~10s ~ms
单机部署 需主备
时间点恢复
同步开销 0(备份时刻才有) 极低(WAL 增量) 中(流复制)
成本 几乎 0 存储费 + 几乎免费 备机 + 网络

SQLite + litestream 在中小规模生产是性价比最高方案之一。

与之前装的 daily backup 共存

之前章节装的 knowledge-backup.timer 是每日全量本机存档;litestream
是实时异地复制。两者互补:

  • 本地 daily 用于"刚才误删一条记录" 快速回滚
  • litestream 用于"机器全没了" 灾难恢复

不冲突,都开就好。

性能影响

litestream 读 WAL 是只读操作,对 application 几乎无影响。
WAL 上传是后台 + 异步,application 写延迟不变。

CPU 占用通常 < 1%,内存 < 50 MB。

踩过的坑

  1. SQLite 必须 WAL 模式:litestream 依赖 WAL。
    sql PRAGMA journal_mode = WAL;
    不是 WAL 时 litestream 报错。Django 我们已经在 settings 里开了。

  2. 不能两个 litestream 同时复制同一个 DB:会写坏。一个机器一个
    实例。

  3. 同时开 cron .backup.backup 命令本身不影响 WAL,安全;
    VACUUM / VACUUM INTO 会重写 DB 让 litestream 失效,需要
    重新 init。

  4. B2 / R2 等 S3-兼容 endpoint URL 易写错:每个区域 endpoint
    不同。出错时 litestream replicate 报 "no such bucket"。
    curl 测试一下访问。

  5. 首次 restore 时 generation 不匹配:DB 被本地写过新数据,
    litestream WAL 链断了。生产里数据始终从备份 restore,本地不要
    手动改。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。