WAL 推送为何总卡 IO

Postgres WAL 推送 S3 单 segment 要 5 秒,跨云双写还要维护两套 SDK。tobi/walgit 把 Git 协议塞进 WAL 归档,1938 star 的小工具到底能省多少 IO?3 个真实问题带你从 0 跑通配置与跨云复制。

源仓库: tobi/walgit

tobi/walgit 是一个把 PostgreSQL WAL 归档对齐到 Git 工作流的命令行工具。截至 2026-08-27,它在 GitHub Trending 周榜拿到 1938 颗 star,最近一周新增 412。它的思路很反直觉:把每段 WAL 文件当作一次 commit,本地用 content-addressable 存储,远程走 Git 协议(HTTP、SSH、s3:// 都能复用),与传统 WAL-G 直接走对象存储 PUT 的路线完全不同。它火起来的原因很直接——团队在把生产 Postgres 迁向多云时发现,云厂商对象存储的 PUT/HEAD 抖动会被原样放大成 RPO,而 Git 的内容寻址天然适合跨云复制。本文不评测好坏,只拆解四个让你今天就能跑起来的小问题。

问题一:单 segment 推送为何要 5 秒

现象:用 WAL-G 把 16MB 的 WAL segment 推到 S3,单次 PUT 居然稳定在 3-5 秒;同一份 segment 走 walgit 只需要 0.4 秒。

根因:WAL-G 是 PUT + HEAD + checksum 三段式 round-trip,每一步都要等对象存储确认;而 walgit 复用 Git 的 packfile 协议,多 segment 共享一份 pack,metadata 和 chunk 在同一条 TCP 流里合并发送,等价于把 N 个 PUT 压成 1 个 PUT。

解法:把 pack.window 调大,并显式声明 wal.segment_size。下面这段是 ~/.walgit/config.toml 的最小可跑配置:

[remote]
backend = "s3"
bucket = "prod-pg-wal"
region = "ap-northeast-1"

[pack]
window = 250
depth = 250

[wal]
segment_size = 67108864

walgit push /var/lib/postgresql/16/main/pg_wal/0000000100000000000000A0,观察日志里的 pack.size 与 rtt.ms 两个指标。如果 pack.size 始终小于 1MB,说明 segment 太碎,先把 postgresql.conf 的 archive_timeout 从 60s 调到 600s。

问题二:PITR 怎么做出「分支化恢复」

现象:DBA 想在演练环境恢复到 14:23:07 的状态,传统 PITR 要先拉 80GB 全量 base backup,再线性回放所有 WAL,等 40 分钟。

根因:传统 PITR 只有时间轴,没有「快照 + 分支」概念;walgit 引入了 git 风格的 ref,你可以给任意一次 push 打 tag,恢复时按 ref 解引用,跳过中间 commit 的回放。

解法:归档前先打一个 time-travel tag:

walgit tag prod-2026-08-27-14:23:07 \
  --message "before schema migration" \
  --ref refs/tags/prod

恢复用 walgit restore --from prod-2026-08-27-14:23:07 --target /tmp/recover,它会先 fetch pack,再按 ref 解引用,最后调用 pg_basebackup 流式接口。注意:tag 名必须包含时区偏移(+08Z),否则 walgit 默认按 UTC 解释,跨时区团队容易踩坑。

问题三:跨云双写怎么不再维护两套 SDK

现象:同一份 WAL 既要落 AWS S3 又要落阿里云 OSS,多云容灾时双写代码在 SDK 层就打架,团队还得分一份人力维护备份清单同步。

根因:WAL-G 用 s3:oss: 两套前缀,每多一个云就要单独写一份 backup-list;walgit 把 remote 抽象成 Git remote,多个 url 直接并列在配置里。

解法:~/.walgit/config.toml 里写:

[[remote]]
name = "aws"
url = "https://s3.amazonaws.com/prod-pg-wal"

[[remote]]
name = "alicloud"
url = "https://oss-cn-hangzhou.aliyuncs.com/prod-pg-wal"

walgit push --all 双写;用 walgit fsck --remote aws 校验一致性。注意:跨云的 pack 必须用同一套 hash 算法(默认 SHA-256),否则 diff 时会报 object format mismatch——这是从 SHA-1 老仓库迁过来的人最容易踩的坑。

问题四:旧 WAL-G 备份怎么平滑迁过来

现象:已经在生产跑 WAL-G 一年的团队想迁 walgit,结果发现 base-backup 格式不兼容,旧备份全废,DBA 拒绝签字。

根因:WAL-G 把 base backup 打包成 tar.lz4 直接放对象存储;walgit 要求 base backup 拆成多个 blob 对象再走 packfile,两边的 manifest 格式对不上。

解法:跑一次性的迁移命令:

walgit migrate \
  --from walg \
  --source s3://old-bucket \
  --target s3://new-bucket \
  --concurrency 8

工具会下载 tar.lz4、解析 manifest、把每个 chunk 当 blob 写进新 bucket,并自动生成对应的 ref。转换期间 postgres 端不需要停机,但建议在低峰期执行。完成后用 walgit verify --ref refs/heads/main --deep 验证对象完整性——deep verify 会比 WAL-G 自带的 check 慢 20-30%,因为它要逐 blob 校验 SHA-256。换来的是 ref 链可审计,旧备份不再是一坨黑盒 tar 包。

参考来源

  • GitHub Trending 2026-08-27(tobi/walgit 排进 Daily 前 10)
  • r/PostgreSQL 讨论串 “WAL archiving with Git semantics”(8 月 24 日开帖,126 个回复)
  • Hacker News 上 tobi 自述设计动机的 thread(ID: 41238591)
  • 项目 README 中的 benchmarks 章节(截至 v0.4.2)