内容提要
pg_hardstorage 采用内容寻址存储,按 SHA-256 引用数据块,不依赖链式增量备份,因此任一备份损坏或删除旧备份均不影响其他备份。实测 487 GiB 数据去重率 87.5%,存储从 89.2 TiB 降至 12.4 TiB。代价是备份时需读取完整数据目录,快照加速功能尚未发布。
延伸解读
链式增量备份的脆弱性
文章指出,链式增量备份(如 pgBackRest 默认模式、Barman 增量模式)中,每个增量都直接引用前一个备份,形成依赖链。这种结构在正常工作时没问题,但一旦链中任一备份损坏,下游所有备份都会失效。更危险的是,问题往往在恢复时才暴露,尤其是在凌晨三点的紧急恢复场景中。pg_hardstorage 通过内容寻址避免了这种单点故障。
内容寻址如何消除链依赖
pg_hardstorage 的清单文件通过 SHA-256 哈希引用数据块,而不是引用前一个清单。每个块的文件名就是其哈希值,因此两个备份共享数据时,是在存储层共享块,而非通过“父指针”关联。删除旧备份不会影响新备份的块,直到垃圾回收发现零引用。这种设计让备份之间完全独立,删除历史中的任意备份都不会破坏其他备份。
去重效果与存储节省
在 487 GiB 的生产级数据集上,每小时备份持续一周,总块数为 1,247,883,唯一块数为 156,423,去重率达 87.5%。总存储占用从原始 89.2 TiB 降至 12.4 TiB。每次备份新增块数约为 1,200 ± 400。这表明内容寻址在去重方面与链式增量备份具有竞争力,同时消除了链依赖。
当前代价与未来改进
pg_hardstorage 目前每次备份都需要读取完整的 PostgreSQL 数据目录,然后与块池进行去重。对于 100 TB 的数据库和慢速存储,这并非没有成本。作者正在开发基于文件系统级写时复制(COW)快照的快速路径,但尚未发布。因此,当前的主要代价是源端 I/O 略高,换来的是可独立检查的清单格式、无隐藏顺序约束的删除模型,以及无法被破坏的备份链。
Q&A
pg_hardstorage 为什么没有增量链?
pg_hardstorage 采用内容寻址存储,每个数据块以 SHA-256 哈希命名,备份清单直接引用这些块,而不是引用前一个备份。因此不存在链式依赖,任一备份损坏或删除旧备份都不会影响其他备份。
pg_hardstorage 的去重效果如何?
在 487 GiB 生产级数据上,每小时备份一周,去重率达到 87.5%,总存储从原始 89.2 TiB 降至 12.4 TiB。
pg_hardstorage 的备份性能有什么代价?
目前每次备份都需要读取完整的 PostgreSQL 数据目录,然后与块池进行去重。对于 100 TB 的数据库在慢速存储上,这会产生额外的 I/O 开销。快照感知的快速路径尚未发布。
pg_hardstorage 与链式增量备份相比有什么优势?
链式增量备份中,任何一个备份损坏都会导致下游所有备份失效。pg_hardstorage 没有链式依赖,删除中间备份不会破坏其他备份,且清单格式可以用 jq 直接查看。
pg_hardstorage 的清单格式是什么样的?
清单是一个 JSON 对象,包含备份 ID 和一个 chunks 数组,数组元素是数据块的 SHA-256 哈希值。例如:{"id": "prod-2026-05-02-0334", "chunks": ["7e1f2a…ab", "9c4d3b…12", "2faabc…77"]}。
pg_hardstorage 删除旧备份会影响新备份吗?
不会。删除旧备份后,新备份的块会保留,直到垃圾回收发现这些块没有任何引用时才会被清理。