pg_hardstorage:用复制协议、内容寻址存储和开放格式重做 PostgreSQL 备份

2026-07-16 24 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

PostgreSQL 备份工具并不少:pgBackRest、Barman 和 WAL-G 已经支撑了大量生产系统。pg_hardstorage 的出发点不是替代这些成熟项目,而是增加一个可以审计、可以迁移、适合云原生部署的开源选项。它选择 PostgreSQL 复制协议作为数据平面,通过普通 libpq 连接持续接收 WAL,因此同一套架构可以面对托管 PostgreSQL、裸机实例和 Patroni 集群。

比功能列表更值得关注的是它背后的工程判断:备份系统必须允许操作员验证实现、演练恢复,并在工具不再适合时保留迁移路径。

为什么从复制协议接收 WAL

传统连续归档通常依靠 PostgreSQL 的 archive_command:数据库生成一个 WAL 段后,执行外部命令把文件复制到备份仓库。这种方式成熟可靠,但它要求操作系统文件访问和服务器侧命令执行。在 RDS、Cloud SQL、Aiven、Supabase、Neon 等托管环境中,用户通常无法控制这些接口。

pg_hardstorage 改用流复制协议。备份代理像流复制副本一样建立连接,并通过自己持有的复制槽跟踪消费位置。这个决定带来几个直接结果:

  • 不再要求配置 archive_command,部署边界更接近数据库连接边界。
  • 托管数据库和自建集群可以共享同一种 WAL 获取方式。
  • 复制槽提供明确的背压机制,数据库知道消费者读到了哪里。
  • Patroni 切换主节点后,代理可以根据 Patroni REST API 重新发现领导者,而不是长期绑定一个主机名。

复制槽也带来必须监控的风险。如果代理停止消费,主库会为了复制槽保留 WAL,最终可能占满磁盘。接入任何基于复制槽的备份工具时,都应同时监控槽的滞后量、WAL 目录空间和备份代理存活状态。

可以这样检查当前复制槽及其 WAL 滞后量;将连接参数替换为你的 PostgreSQL 管理连接:

psql "host=127.0.0.1 port=5432 dbname=postgres user=postgres" -X -v ON_ERROR_STOP=1 <<'SQL'
SELECT
    slot_name,
    slot_type,
    active,
    restart_lsn,
    confirmed_flush_lsn,
    pg_size_pretty(
        pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)
    ) AS retained_wal
FROM pg_replication_slots
ORDER BY slot_name;
SQL

这条查询适合作为巡检基础,但告警阈值不能照搬固定数字。应根据 WAL 生成速率、磁盘余量和允许恢复点目标设置阈值。

内容寻址让双路 WAL 不再等于双倍存储

pg_hardstorage 使用 FastCDC 分块和内容寻址去重。内容寻址存储的核心思想是:对象身份由内容摘要决定,相同内容只需保存一次。于是,代理可以同时从主库和低延迟副本接收 WAL;重复数据经过寻址后不会线性增加仓库存储量。

这种设计与链式增量备份的取舍不同。链式增量通常依赖一个基线和后续差异,恢复时需要正确拼接整条依赖链。内容寻址分块把复用关系下沉到块级别,有利于去重和并行验证,但也提高了元数据、垃圾回收和引用一致性的重要性。

v1.0 还包含 AES-256-GCM-SIV 信封加密和按租户执行加密擦除的能力,并支持 AWS KMS、GCP KMS、Azure Key Vault、Vault Transit 以及 PKCS#11/HSM。这里的边界要说清楚:删除密钥可以让对应密文失去可解密能力,但团队仍需验证密钥备份、轮换、权限隔离和审计流程,不能把“用了 KMS”等同于“合规已经完成”。

Patroni 感知和迁移兼容性

高可用集群最危险的时刻不是稳定运行期,而是领导者切换期间。pg_hardstorage 从设计上读取 Patroni REST API,并用四个协作机制维持 WAL 连续性。项目给出的目标是:故障转移后约五秒完成重新连接,同时保持 WAL 无缺口。

操作员仍应通过演练验证这一行为。至少要覆盖:备份代理运行时切换主节点、旧主节点不可达、网络短暂分区、复制槽状态变化,以及从指定时间点执行实际恢复。仅看到“备份任务成功”不能证明恢复链完整。

另一个实用设计是兼容层:项目提供 pgBackRest CLI shim 和 Barman archive_command shim,使现有自动化可以在迁移窗口中继续工作。它降低的是切换期间的编排成本,而不是免除验证。迁移时应并行保留旧工具,比较恢复点和恢复结果,再决定何时停掉旧链路。

本地构建并启动一次性测试集群

下面的命令来自项目提供的构建和开发入口。运行前需要准备 Git、项目编译依赖,以及可用于开发集群的容器环境;具体依赖以仓库文档和 compile.sh 的检查结果为准。

git clone https://github.com/cybertec-postgresql/pg_hardstorage
cd pg_hardstorage
./compile.sh
./bin/pg_hardstorage --help

如果想直接启动一次性的 PostgreSQL、代理和备份仓库,可以运行:

cd pg_hardstorage
./scripts/devcluster.sh up

不要把“开发集群成功启动”当作验收结束。可以这样实践一轮最小恢复演练:

  1. 启动开发集群并确认代理持续接收 WAL。
  2. 创建一张测试表,写入带时间戳的唯一记录。
  3. 触发基础备份,并记录对应恢复点。
  4. 再写入一批数据,然后模拟 Patroni 或数据库主节点切换。
  5. 恢复到隔离环境,核对目标记录、时间线和 WAL 连续性。
  6. 保存恢复耗时、所需人工步骤和验证查询,纳入日常演练。

项目建议把缺陷报告写成可运行的 testkit 场景,并使用 pg_hardstorage_testkit scenario reproduce 重现。这类报告比日志截图更容易定位回归发生在哪个提交。

v1.0 的边界比功能数量更重要

v1.0 支持文件系统、S3、GCS、Azure Blob 和 SFTP 五类存储后端,并提供 Docker 验证沙箱;Firecracker microVM 验证器需要构建标志启用。审计方面包含哈希链 Merkle 日志和透明日志锚定,发布物则带有 Cosign 签名、SLSA Level 3 构建来源以及 syft 生成的 SBOM。项目还承诺线格式在 24 个月内向后兼容。

同样重要的是没有进入 v1.0 的内容:没有超出 systemd timer 或 Kubernetes CronJob 的内建调度器,没有 Web UI,没有快照加速路径,也没有公开的 Tier-2 插件注册中心。CLI 通过 --output json 面向自动化,插件目前通过 $HSPLUGIN_PATH 加载。

这些删减让首个版本聚焦于跨环境可用的流式路径,但也会影响采用决策。依赖存储快照实现极短备份窗口、要求图形化操作台,或需要集中插件治理的团队,应等待对应能力成熟,或者继续使用现有工具。

采用前的检查清单

切换备份工具不应因为“有新工具”而发生。如果当前系统能稳定恢复,就没有必要为了技术新鲜感迁移。更合理的触发条件是:托管 PostgreSQL 无法使用服务器侧归档、Patroni 切换频繁造成 WAL 采集中断、需要多云 KMS/HSM,或需要明确的开放格式和供应链证明。

评估时至少完成以下工作:

  • 在隔离环境验证完整恢复、时间点恢复和跨时间线恢复。
  • 对复制槽滞后、WAL 保留空间和代理断连设置告警。
  • 验证对象存储不可用、KMS 不可用和 Patroni 切换时的行为。
  • 校验 Cosign 签名、构建来源和 SBOM,而不只是下载二进制运行。
  • 利用 pgBackRest 或 Barman shim 并行迁移,保留可回退窗口。
  • 明确 24 个月格式兼容承诺是否覆盖组织的数据保留周期。
  • 定期从备份恢复业务数据,并让验证结果进入审计记录。

pg_hardstorage 最有价值的信号,不是又增加了一个备份命令,而是把“可选择、可检查、可迁移”视为备份系统本身的功能。Apache 2.0、无企业版功能切割、无 CLA,以及公开的安全和供应链能力,为这种主张提供了可验证的基础;最终是否适合生产环境,仍应由恢复演练、故障注入和长期运行数据来回答。


相关推荐