很多DBA做PostgreSQL备份,第一反应就是写个 cron 脚本,定时调 pg_dump。这套逻辑在几十 GB 的小库上确实够用,但当你手里管着几百 GB 甚至上 TB 的生产库,还要回答“我能恢复到什么时间点”“备份到底能不能用”这两个问题时,pg_dump 方案就会露怯。Barman 就是专门解决这个问题的老牌开源工具,它帮你把全量备份、WAL 归档、保留过期、恢复演练这些日常操作全部串成一套可管理的工作流,这也是我这两年给 PostgreSQL 项目搭备份体系时最常用的方案。
这篇内容面向的是正在从“手动备份”过渡到“自动化备份管理”的 DBA、运维工程师,以及被一纸备份方案搞得头大的后端开发者。我会从环境规划、配置项含义、备份执行、恢复演练到问题排查,全程按生产环境的操作习惯来讲。每个参数为什么这样配、踩过哪些坑,我会直接写在对应的位置,你照着搭基本不会走弯路。
1. 选择 Barman 之前,先想清楚三个问题
工具选型这事儿,最怕一上来就照着文档堆配置。你得先明确自己的备份目标到底属于哪一层,Barman 擅长解决什么,不擅长解决什么,心里有数再动手。
1.1 逻辑备份和物理备份,差别在哪儿
PostgreSQL 的备份方式粗分两类。pg_dump 属于逻辑备份,它把数据用 SQL 语句的形式导出来,恢复时需要把语句重新执行一遍,本质上是在“抄写笔记”。物理备份则是直接复制数据库的底层文件,相当于把整本笔记本拿去复印店复印一份。区别在于:
- 逻辑备份只能恢复到命令执行那一刻的状态,备份之后产生的新数据全部丢失。
- 物理备份配合 WAL(预写日志),可以把数据库恢复到任意一个历史时间点,这就是常说的时间点恢复(PITR)。
Barman 做的是物理备份。它在底层调用 pg_basebackup 或 rsync,在备份期间协调 PostgreSQL 的 WAL 状态,让备份目录和 WAL 形成一个完整一致的还原点。恢复的时候,Barman 再把对应的 WAL 重放到指定时间戳,做到“随便挑一分钟恢复”。
我见过不少团队用 pg_dump 做“全量备份”,恢复时才发现备份文件是好的,但业务数据已经丢了一个小时,因为全量备份和业务高峰之间有窗口,期间的数据谁也没办法补回来。物理备份 + WAL 的方案才真正把恢复点目标(RPO)降到了分钟级甚至秒级。
1.2 Barman 和常见替代方案的真实差距
拿几种我实际接触过的方案做个横向对比,这样你判断起来会更快。
| 方案 | 是否支持 PITR | 是否自动管理 WAL | 是否集中管理 | 恢复操作复杂度 | 适用阶段 |
|---|---|---|---|---|---|
| 自写脚本 + pg_dump | 否 | 否 | 否 | 简单但恢复点陈旧 | 几十 GB 以内小库 |
| 自写脚本 + pg_basebackup + 手工归档 WAL | 勉强 | 靠自己写逻辑 | 否 | 恢复要手工拼接,容易错 | 有经验但没工具链的团队 |
| pgBackRest | 支持 | 支持 | 支持 | 配置偏复杂,学习曲线陡 | 对备份速度和并行压缩有强需求 |
| Barman | 支持 | 支持 | 支持 | 命令简洁,上手快 | 大多数 PostgreSQL 生产环境 |
Barman 的强项是“集中管理”。你可以在单独的备份服务器上管理多个 PostgreSQL 实例,每个实例一个配置文件,备份状态、WAL 接收、过期清理都由 Barman 统一调度。相比之下,自写脚本的方式最大的问题不是写不出来,而是每个人写的都不一样,接手的人完全看不懂上一任留下的脚本逻辑。
pgBackRest 在并行、压缩、增量备份上也有自己的优势,但如果是传统运维团队,Barman 的命令风格更贴近 PostgreSQL 社区习惯,文档齐全,遇到问题搜一下基本都有答案。我是建议中小团队优先考虑 Barman,它把很多脏活累活都封装好了。
1.3 什么时候不适合上 Barman
不是所有场景都适合 Barman,遇到下面这些情况,我会明确劝退:
- 只有一个几 GB 的开发库,丢一天数据也无所谓。那直接 pg_dump 就行,别为它单独养一台服务器。
- 你的需求是做表级恢复,而不是整库恢复。Barman 恢复的最小粒度是完整实例,如果你想误删了一张表后快速找回,那还是要靠 pg_dump 按表备份兜底。
- 跨机房网络质量差到连 SSH 都不稳定。Barman 的备份和 WAL 传输依赖可靠的网络链路,网络丢包严重时备份会频繁失败,反而增加运维压力。
搞清楚这些边界,你才知道 Barman 应该摆在自己的备份体系里的哪个位置。通常我的做法是:Barman 负责整库物理备份 + 时间点恢复,pg_dump 作为表级导出工具在需要时手动执行,两者并不冲突。
2. 环境准备与安装:两台机器的基础设施
Barman 天生是“主备分离”的架构,备份服务器独立于数据库服务器。这样设计的好处是数据库服务器挂了,备份还在另一台机器上,不会“一锅端”。我见过有人把 Barman 装在数据库服务器本机上,真出事的时候两台服务一起宕,备份全废,这个坑千万不要踩。
2.1 拓扑规划和目录设计
推荐的最小拓扑是一台 PostgreSQL 生产服务器加一台 Barman 备份服务器,两台机器放在同一个机房或同一个可用区,网络延迟要低。备份服务器不需要很高的 CPU,但磁盘容量要按备份策略提前算清楚。
我一般这样规划目录:
- Barman 程序安装目录:
/usr/bin或虚拟环境目录 - Barman 主配置:
/etc/barman.conf - 实例配置目录:
/etc/barman.d/ - 备份数据根目录:
/var/lib/barman/<实例名>/ - Barman 日志:
/var/log/barman/barman.log
其中/var/lib/barman一定要单独挂一块数据盘,不要和系统盘共用。原因很简单:备份文件增长快,如果系统盘被备份占满,操作系统本身就会出问题,到时候连排查的空间都没有。
磁盘容量估算我给一个实际例子。假设库大小 500GB,数据库每天产生 20GB 的 WAL,我的策略是保留 2 个全量备份,WAL 保留 7 天。那么需要的空间大约是:
全备 500GB × 2 份 = 1000GB,WAL 20GB × 7 天 = 140GB,总需求约 1140GB,再预留 20% 余量,实际要准备大概 1400GB 的备份盘。如果启用了压缩,实际占用会小一些,但余量建议不要省,Barman 在做恢复演练时需要额外空间存放恢复出来的数据目录。
2.2 安装 Barman 的三种方式
Barman 是 Python 写的,安装方式灵活,我用过的有三种。
第一种,用发行版自带的包管理器。在 Debian/Ubuntu 上执行apt install barman,在 CentOS/RHEL 上执行yum install barman。这种方式最省事,但要注意发行版自带的版本可能偏老。Barman 的版本直接影响它支持的 PostgreSQL 版本,如果生产库是 PostgreSQL 15 或更高,建议用较新的 Barman 3.x。
第二种,从 PostgreSQL 官方软件源安装。这个源会持续更新 Barman,版本比较新,兼容性也好。添加官方源后再执行包管理器安装即可。
第三种,用 pip 装在独立虚拟环境里。适合那些不想动系统 Python 环境的机器。创建虚拟环境后执行pip install barman,然后手动创建 barman 用户和目录结构。
安装完成第一件事是检查版本:barman --version。我建议至少用 3.5 以上版本,PG 13 之后的版本特性支持得更完整,比如流式 WAL 压缩、基于时间线的恢复等能力都更稳。
2.3 SSH 免密配置:第一步最容易错
Barman 和 PostgreSQL 之间通过 SSH 执行远程命令,比如拉取备份、执行归档命令。所以必须配置从 Barman 服务器的barman用户到 PostgreSQL 服务器上的postgres用户的免密登录。
配置步骤:
# 在 Barman 服务器上,以 barman 用户执行 su - barman ssh-keygen -t ed25519 -C "barman-backup" cat ~/.ssh/id_ed25519.pub把生成的公钥追加到 PostgreSQL 服务器的postgres用户的~/.ssh/authorized_keys文件里,权限要严格设置为:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys然后回到 Barman 服务器验证连通性:
su - barman ssh postgres@<pg服务器IP> "echo ok"如果输出不是 ok,优先检查 authorized_keys 权限和 SELinux 配置。这个环节我踩过太多次坑,最常见的就是公钥文件权限是 644,SSH 直接拒绝使用,错误信息还没写清楚,很容易让人误判成网络问题。
另外建议在 Barman 配置文件里给 SSH 加上连接复用参数,减少反复握手带来的延迟:
ssh_options = -o ConnectTimeout=10 -o ControlMaster=auto -o ControlPath=/tmp/barman-ssh-%r-%h-%p -o ControlPersist=300这样连续执行备份、归档、检查命令时,SSH 连接可以复用,备份窗口能缩短不少。
3. PostgreSQL 侧配置:让数据库先把 WAL 交出来
Barman 的核心优势在于 WAL 的自动归档和保留,所以 PostgreSQL 侧的配置目标很明确:让数据库能够安全地生成 WAL 并把它们传出去,同时允许 Barman 通过流复制协议读取数据。
3.1 关键参数设置与含义
在postgresql.conf里,以下几项必须重点确认:
wal_level = replica archive_mode = on archive_command = 'ssh barman@<备份服务器IP> "barman receive-wal --get-wal <实例名> %p"' archive_timeout = 300 max_wal_senders = 5 wal_keep_size = 512MB逐个说一下为什么这么配。
wal_level至少要replica,只有这个级别才会在 WAL 里写够恢复所需的信息。逻辑复制场景下还要用logical,但纯备份用replica就够了。
archive_command是一条外部命令。当 PostgreSQL 决定归档一个 WAL 文件时,会把%p(WAL 文件的完整路径)传给这条命令。这里的写法是通过 SSH 把 WAL 文件交给 Barman 服务器上的receive-wal进程,由 Barman 统一保存。如果你更习惯用 rsync,也可以写成 rsync 推送,但 SSH 方式更干净,不依赖额外组件。
archive_timeout设成 300 秒,意思是即使业务完全空闲,最多 5 分钟也会切一次 WAL。这么做的好处是 Barman 接收 WAL 的延迟不会太久。代价是会多产生少量空 WAL 文件,但每个文件默认 16MB,一天多几十个也不是大问题。这个参数很多人忽略,结果就是备份机看到的 WAL 一直不更新,恢复时才发现最新数据根本没归档。
max_wal_senders是允许的 WAL 发送进程数。Barman 的流式接收至少要占 1 个 slot,如果你还有从库,要在这个数字上多留几个。
3.2 pg_hba.conf 授权设计
Barman 有两种方式获取数据:一种是基于流复制的pg_basebackup,另一种是基于文件复制的rsync。无论哪种,都需要数据库允许远端连接。在pg_hba.conf里加两条规则:
host replication postgres <备份服务器IP>/32 md5 host all postgres <备份服务器IP>/32 md5第一条放行复制协议连接,这是pg_basebackup和流式 WAL 接收必需的;第二条放行普通的数据库连接,用于 Barman 查询数据库状态、执行pg_start_backup()这类函数。
我习惯在postgresql.conf里把监听地址也显式写出来:
listen_addresses = '0.0.0.0'默认只监听 localhost,如果你发现 Barman 一直连不上,第一反应检查这个参数,然后是 pg_hba.conf 的规则顺序。pg_hba.conf 是自上而下匹配的,如果前面有拒绝规则,后面的允许规则不会生效。
改完两个文件后记得重启或pg_ctl reload。archive_command 不需要重启,但 wal_level、listen_addresses 这些需要。
3.3 验证 WAL 归档链路
配置完之后先别急着让 Barman 做全量备份,验证一下 WAL 能不能正确流过去。手动切换一次 WAL:
SELECT pg_switch_wal();然后在 Barman 服务器上查看:
su - barman barman list-files --wal <实例名> | tail -10如果能看到刚生成的 WAL 文件出现在列表里,说明归档链路已经通了。如果迟迟看不到,去 PostgreSQL 服务器上看 PostgreSQL 日志,里面会记录 archive_command 的具体报错。这一步是后面所有操作的基础,宁可在这里多花十分钟,也不要在恢复演练时才追查。
4. Barman 侧配置:把备份策略落实到配置文件
Barman 的配置分两层:全局配置和实例配置。全局配置写公共项,实例配置写每个数据库特有的连接信息。我强烈建议每个 PostgreSQL 实例一个独立配置文件,放在/etc/barman.d/下,文件名就是实例名。
4.1 一份可以直接抄作业的全局配置
/etc/barman.conf长这样:
[barman] barman_home = /var/lib/barman barman_user = barman log_file = /var/log/barman/barman.log compression = zstd reuse_backup = link retention_policy = retention RECOVERY WINDOW OF 7 DAYS ; 让 Barman 定期自动执行调度任务 ; 配合 cron 里的 barman cron 使用 parallel_jobs = 4compression = zstd是我目前最推荐的压缩算法。gzip 压缩率高但非常吃 CPU,备份 500GB 的库能把 CPU 跑满很长时间。zstd 在压缩速度和压缩率之间取得了很好的平衡,实测比 gzip 快一倍以上,压缩率差距只有几个百分点。如果你用的 Barman 版本较老不认识 zstd,退而求其次选 lz4,速度也快,但压缩率略低。
reuse_backup = link是针对 rsync 备份方法的优化选项,它会在新备份和旧备份之间复用相同内容的文件,用硬链接代替复制,能显著节省磁盘和备份时间。但要注意,如果你用的是backup_method = postgres,这个参数会被忽略,这是版本差异,下面会细说。
retention_policy = retention RECOVERY WINDOW OF 7 DAYS表示要保证能恢复到过去 7 天内的任意时间点。Barman 会自动据此判断哪些全量备份可以删、哪些 WAL 可以清,不用你手动干预。
4.2 备份方法选型:rsync 还是 postgres
这是配置时一定会遇到的选择题。Barman 支持两种全量备份方法:
backup_method = rsync:Barman 在数据库服务器上通过 SSH 执行 rsync,直接把数据目录拉过来。配合reuse_backup = link可以做增量硬链接备份,对磁盘空间敏感的环境非常友好。backup_method = postgres:Barman 在数据库服务器上调用pg_basebackup,这是 PostgreSQL 官方的物理备份工具,标准、稳定、兼容性最好。
我的建议是:如果是 PostgreSQL 13 以上版本,默认选postgres。原因有两条。第一,pg_basebackup 是官方持续维护的工具,对各种新特性的兼容性有保障;第二,rsync 方式需要 Barman 对数据目录进行文件级遍历,数据库文件特别多时,元数据扫描本身就慢,备份窗口会被拉长。postgres 方法整体更干净。
如果你确实依赖硬链接增量特性来省空间,那可以用 rsync 方法,但要在配置里打开reuse_backup = link。这个模式下备份速度和空间占用都有优势,只是牺牲一点兼容性,生产环境只要测试充分也能接受。
4.3 实例配置:连接信息和流式 WAL
每个实例的配置文件/etc/barman.d/pg-server.conf:
[pg-server] description = "生产主库" ssh_command = ssh postgres@<pg服务器IP> conninfo = host=<pg服务器IP> user=postgres dbname=postgres backup_method = postgres streaming_archiver = on streaming_conninfo = host=<pg服务器IP> user=postgres dbname=postgres slot_name = barman_slotssh_command是 Barman 远程执行命令的方式,对应第二节里的免密配置。conninfo是 Barman 连接 PostgreSQL 数据库的连接串。streaming_archiver = on开启流式 WAL 接收,它会在 Barman 服务器上启动一个类似pg_receivewal的进程,主动接收 WAL,而不是完全依赖 PostgreSQL 的 archive_command 推送。
slot_name = barman_slot让 Barman 在 PostgreSQL 上注册一个复制槽。复制槽的作用是告诉 PostgreSQL:“这个备份端还在消费 WAL,别把我需要的 WAL 删掉。”这是防止 WAL 被提前清理的关键机制,否则业务高峰期 WAL 产生太快,PostgreSQL 可能还没来得及归档就把旧 WAL 覆盖了,备份链条就断了。
启用流式接收后,首次要给 Barman 创建这个复制槽:
su - barman barman receive-wal --create-slot pg-server创建完成后,Barman 的 cron 任务会在后台拉起 receive-wal 进程,持续消费 WAL。这里要提一句:archive_command作为第二通道也不要关掉,它是一种“双保险”。即使流式进程意外挂了,归档命令还能把 WAL 推过来,避免缝隙。
4.4 barman check 全项体检
配置写完后,第一件事不是急着备份,而是先体检:
barman check pg-server输出会逐项列出 PostgreSQL 版本、系统标识、目录权限、replication slot、归档策略等信息。每一项出现WARNING都值得多看一眼。常见的 WARNING 集中在:
archiver警告:说明 archive_command 没配好,或者是 pg_hba.conf 没放行。replication slot警告:说明复制槽没创建,流式接收不会工作。directory警告:说明备份目录权限不对,barman 用户无法写入。
我的原则是:barman check不出现任何WARNING和ERROR之前,坚决不做第一次全量备份。否则你会在一个不健康的基础上叠加更多问题,排查起来会很痛苦。
5. 第一次完整备份与 WAL 流式接入
到这一步,基础设施已经齐了。第一次备份我建议以交互式命令执行,不要急着写进 cron,因为你需要在终端里盯着备份过程,感受它的耗时、输出和潜在问题。
5.1 执行首次全量备份
su - barman barman backup pg-server命令执行期间会有进度输出,显示备份开始时间、结束时间、备份大小、耗时、WAL 数量等。整个过程的长度取决于数据库大小、磁盘 IO 和网络带宽。第一次跑出来后记下耗时,后面做备份窗口规划和容量估算都用得上。
备份完成后,查看状态:
barman list-backups pg-server barman show-backup pg-server latestshow-backup的输出里重点看Status字段,必须是DONE。如果看到FAILED,直接去看 Barman 日志/var/log/barman/barman.log,里面会记录失败的具体原因。首次备份最常见的失败原因是权限问题,比如 pg_hba.conf 没放行、postgres 用户无法读数据目录等。
顺便说一句:Barman 的全量备份默认是“透明地”结合 PostgreSQL 的检查点机制,备份开始时会请求一个检查点,确保文件系统快照和 WAL 位置一致。所以备份期间数据库的性能会有轻微波动,这在正常范围,不用太紧张。
5.2 解读备份目录结构
备份完成后,/var/lib/barman/pg-server/下大致是这个结构:
base/:存放每个全量备份的子目录,命名是时间戳,比如20250115T100000。wal/:存放从 PostgreSQL 接收到的 WAL 文件。incoming/:归档命令推送 WAL 时临时落地的目录。recovery/:某些恢复操作产生的中间文件。
理解这个结构对排查问题很有帮助。比如你发现 WAL 一直不过来,可以先看incoming/有没有文件堆积。如果文件堆积而不消失,说明 Barman 的接收进程或后续的处理逻辑有问题,常见原因是文件所有权不对或收到的文件校验失败。
5.3 流式 WAL 接收的验证与日常观察
配置了streaming_archiver之后,Barman 的 cron 任务会自动启动接收进程。验证它是否正常工作:
barman status pg-server输出里应该有一行显示 receive-wal 进程的状态。如果显示未运行,可以用手工方式启动接收:
barman receive-wal pg-server这个命令会以前台方式启动接收进程,方便观察日志。确认正常后按 Ctrl+C 退出,再交给 cron 管理。
日常观察 WAL 是否持续流入,最简单的办法是看 wal 目录里的文件变化:
watch -n 5 "ls -l /var/lib/barman/pg-server/wal/ | tail -5"文件时间戳应该持续更新。如果长时间没有新文件,先去数据库服务器上执行SELECT pg_switch_wal();手动切换一次,再观察 Barman 侧有没有反应。没有反应的话,按第八节的排查思路走。
5.4 备份完整性和一致性校验
Barman 每次备份完成后,都会自动执行一致性检查,确保备份数据目录和 WAL 的衔接是完整的。你想主动验证也可以:
barman check-backup pg-server它会模拟一次恢复前的校验,报告备份是否一致、是否缺少 WAL 文件。我建议把check-backup也纳入定期任务,比如每天的 cron 里跑一次,早发现问题早处理,别等到恢复时才傻眼。
6. 恢复实战:能把备份救回来才是真本事
备份做了一百次,恢复没练过一次,等于没做备份。这是我一直跟团队强调的话。恢复操作本身不难,但里面有几个细节,都是你在真实故障现场才会体会到的重要程度。
6.1 基础恢复流程 barman recover
把最新备份恢复到本地目录:
barman recover pg-server latest /data/restore_dir这条命令会把全量备份往目标目录还原,同时把需要的 WAL 也拷贝过去,最终得到一个可以直接启动的 PostgreSQL 数据目录。恢复完成后,检查目录权限:
chown -R postgres:postgres /data/restore_dir然后启动 PostgreSQL,设好data_directory指向恢复目录即可。
这里要说一个最常见的误解:barman recover恢复出来的是数据目录,不是整个操作系统,PostgreSQL 软件本身还需要在目标机器上预先安装好,版本要和生产环境一致。很多第一次用的人会以为恢复完就万事大吉,结果发现起不来,日志里报数据目录版本不匹配,那就是软件版本的问题。
6.2 时间点恢复 PITR:精确到分钟的操作
Barman 真正的杀手锏是时间点恢复。假设业务侧报告“今天下午 14:30 有人误删了数据”,你想恢复到 14:25 的状态:
barman recover --target-time "2025-01-15 14:25:00+08" pg-server latest /data/restore_dir在recover命令后带上--target-time,Barman 会自动重放 WAL 到指定时间点,然后停下,生成一个可见恢复标记。
除了时间,还可以按事务 ID 或 LSN 定位恢复点。遇到“误操作发生在某一笔事务之后”的场景,--target-xid更精确:
barman recover --target-xid "208546" pg-server latest /data/restore_dir这两个参数在日常运维中各有适用场景。时间点恢复简单直观,但事务量特别密集时,可能没法精确到“某条语句之前”。事务 ID 恢复更精准,但需要你先知道目标事务 ID,这个数字通常要在问题发生后从日志或别的途径获取。
恢复完成后,我会建议先不要直接切业务。在 PostgreSQL 日志里确认recovery stopping before/at的行,看时间点和预想是否一致。然后把应用以只读模式连上去,让业务侧验证数据,确认无误后再说切换的事。
6.3 恢复到异机:注意路径和配置差异
真实故障中,生产服务器可能整个挂掉,恢复目标是一台新机器。barman recover可以通过--remote-ssh-command直接把数据恢复到远程机器:
barman recover --remote-ssh-command "ssh postgres@<新服务器IP>" pg-server latest /var/lib/postgresql/data这里要留意几点:
- 新机器上 PostgreSQL 版本和编译选项要尽量一致,否则数据目录虽然能拷贝过去,但启动时会报软件版本问题。
- 恢复目录路径最好和生产保持一致。如果路径变了,检查
postgresql.conf里是否有绝对路径配置需要修正,比如unix_socket_directories、log_directory等。 - 恢复出来的数据目录所有权要改成新机器上的 postgres 用户。
异机恢复一定要提前演练一次。我见过最典型的问题是:生产环境数据目录挂在一个自定义路径/data/pgdata,恢复演练时目标机器默认路径是/var/lib/postgresql/data,结果恢复完启动失败,排查半天发现是配置里的绝对路径没改。
6.4 恢复后必须做的四项检查
恢复完成后,我有一套固定的检查清单,按顺序执行:
第一,确认数据库能正常启动:pg_controldata查看状态,或用pg_ctl start观察日志。
第二,确认恢复终止点:执行SELECT pg_is_in_recovery();,正常恢复完成后返回f,表示已经脱离恢复模式,可以接受读写。
第三,抽查关键业务表的数据量和最新记录时间,和故障前的预期比对。
第四,检查 PostgreSQL 日志中是否有FATAL级别的错误。
这套检查 10 分钟内能跑完,但能省掉后续无数麻烦。
7. 自动化与监控:没有定时任务就没有备份
Barman 本身不会自动做任何事情。它提供了完整的命令集,但你必须用 cron 或 systemd timer 把它调度起来。这里只要配置不对,前面的所有工作都会变成摆设。
7.1 cron 调度与 barman cron 机制
Barman 官方推荐的调度方式是把barman cron设为每分钟执行一次:
* * * * * barman cron --barman-cron-check >/dev/null 2>&1barman cron会负责执行这几类工作:
- 启动或维持每个实例的流式 WAL 接收进程
- 执行到达调度时间的全量备份
- 执行备份保留策略,清理过期全量备份和 WAL
- 执行备份完整性校验
把这一切交给barman cron统一管理,而不是在 crontab 里写barman backup,原因是它可以避免任务重叠和目录锁冲突。如果你自己再额外加一个凌晨 1 点的barman backup任务,可能和 Barman 内部的调度打架,备份目录会锁死,导致备份失败。这是新手容易踩的坑:明明配置了 cron,又自己加了一行备份命令,结果两边撞车。
关于全量备份的频率,我用的是每天全备一次,加上持续流式 WAL。备份时间放在凌晨业务低谷,用 Barman 的barman cron内置时间表就够了。如果你业务高峰期数据量巨大,也可以把全备频率降到两天一次,但要确保 WAL 持续流入和保留策略符合你的 RPO 要求。
7.2 监控集成与自建脚本
Barman 自带barman check命令,输出也是稳定的文本格式,很适合被监控系统采集。我习惯在备份服务器上放一个脚本,内容很简单:
#!/bin/bash barman check pg-server > /tmp/barman_check.log 2>&1 if [ $? -ne 0 ]; then # 调用告警接口 curl -X POST "你的告警平台地址" -d "code=barman_check_failed" echo "$(date): unhealthy" >> /var/log/barman_check_history.log fi监控系统只要能执行命令,基本都可以这样接入。如果你用 Prometheus,也可以把 Barman 的指标通过文本采集器暴露出去,但没有现成 exporter 的情况下,脚本 + curl 是成本最低的方式。
监控指标我建议关注这几项:
- 最后一次全量备份的状态和时间
- 最新 WAL 文件的时间戳(超过 10 分钟没更新要警惕)
- 备份目录磁盘剩余空间
- 复制槽的
active状态,确认没有断掉
7.3 容量预估与告警阈值
容量监控不能等磁盘满了才告警。我一般按这个公式设置阈值:
安全线 = 全备大小 × 保留份数 + 日均 WAL 量 × 保留天数 + 恢复演练需要的临时空间
然后加 20% 余量。告警阈值设在这里,一旦磁盘占用超过安全线 80%,就触发告警。别只看剩余多少 GB,因为你不知道 Barman 会在什么时候开始执行下一次全备。如果全备跑到一半磁盘满了,这个备份基本报废,而且清理起来还要花不少时间。
我还建议定期清理恢复演练产生的临时目录。有些人演练完就把恢复目录放在备份盘上忘了删,一次演练可能吃掉几百 GB,再加上常规备份增长,磁盘很容易告警。演练结束后立刻清理,这是我从实践中总结出来的小小教训。
8. 常见问题与排查实录
Barman 用久了,该遇到的问题我基本都碰过一轮。挑几个出现频率高的,按“现象 - 原因 - 排查步骤”的方式写下来,当作速查清单用。
8.1 WAL 堆积,备份目录疯狂膨胀
现象:/var/lib/barman/<实例名>/wal/目录持续增长,Barman 没有按预期清理过期 WAL。
排查思路按顺序走:
第一,执行barman check pg-server,看是否有复制槽相关警告。流式接收依赖复制槽,如果槽被删了,Barman 无法确定哪些 WAL 还被下游消费,就不会清理。
第二,检查barman cron是否真的在跑。很多人配了 crontab,但 cron 服务本身没启动,Barman 的清理逻辑自然永远不会执行。
第三,查保留策略有没有生效。执行barman show-schedule pg-server,看 Barman 是否对过期备份有输出。如果显示没有调度,strategy 里retention_policy需要确认。
WAL 堆积最危险的是拖垮备份盘,进而让后续全备失败。如果发现wal目录异常大,可以手动强制切一次清理:
barman keep pg-server backup_id但这个命令会强制保留指定备份并清理更早的,所以执行前要确认备份 ID 是不是你想要留的,不然误删是回不来的。
8.2 SSH 连接失败与权限问题的定位技巧
现象:barman check报错说无法连接 PostgreSQL 服务器,SSH 通道建立失败。
排查方法:
在 Barman 服务器上手动执行:
su - barman ssh -vvv postgres@<pg服务器IP> echo ok-vvv会打印详细握手过程。常见原因有几类:
- authorized_keys 权限不对,改为 600。
- 目标服务器 SELinux 拦截了 SSH 对 postgres 用户目录的访问。
- PostgreSQL 服务器上的 postgres 用户的 shell 不是
/bin/bash。Barman 的 rsync 方法依赖远程 shell 执行命令,如果 shell 被设置成nologin,SSH 能连上但无法执行命令。 - Barman 配置里的 ssh 用户名写错,比如写成了 barman,而目标机器根本没有这个用户。
这类问题 90% 都可以通过手动 ssh 定位到,不要在 Barman 的命令层面反复试,浪费时间。
8.3 恢复时报“缺少 WAL 文件”
现象:执行barman recover时报错,提示某个 WAL 段在 Barman 侧找不到。
这种情况通常不是 Barman 的锅,而是生产侧 WAL 归档链路曾经断过。最常见的原因是:在某个时间段里,流式接收进程挂了,archive_command 也失败,那段时间的 WAL 已经在生产库上被清理了,所以 Barman 侧缺失这部分日志。
排查办法:执行barman show-backup pg-server latest,看WAL segments字段,对比实际存在的 WAL 文件编号。确认缺失的时间范围后,回到生产库看看是否还有对应的 WAL 文件,如果有,手动把它导入 Barman:
barman put-wal pg-server <wal_folder>然后重新执行恢复。如果没有,那只能接受“已经丢失该段时间数据”的现实,恢复到一个较早的时间点。这也是为什么我一直强调流式接收进程要监控,WAL 断档是 PITR 恢复中最容易让人措手不及的问题。
8.4 全量备份期间具体卡顿或互斥
现象:全量备份执行到一半长时间没有进展,或者和另一个备份任务冲突。
Barman 在同一实例上不允许同时执行两个备份。如果你手动执行了一个barman backup,然后 cron 又发起了下一个,后者会被锁等待。排查时看 Barman 日志,会明确看到类似“another backup is already running for server”的字样。
如果确认没有其他任务在跑,但备份卡住,常见原因是 PostgreSQL 侧执行pg_start_backup()时等待长事务结束。这时去 PostgreSQL 上查活跃事务:
SELECT * FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY xact_start ASC;如果有事务开了很多小时没提交,备份初始化就会卡在起点。这种场景下,我会选择错开备份窗口,优先处理长事务问题,让备份能够顺利走完。
8.5 备份盘被撑爆的处理顺序
现象:备份盘满了,全量备份失败,Barman 管理目录状态混乱。
处理顺序很重要,别慌。第一步,找到可以安全清理的备份。执行barman list-backups pg-server,找出状态为FAILED的备份,它们没有价值,可以删掉:
barman delete pg-server <备份ID>如果已经成功备份不少,且保留策略允许,可以手动删掉最老的一个正常备份:
barman delete pg-server <最老备份ID>注意不要直接rm -rf备份目录,因为 Barman 的元数据会不一致,之后恢复操作可能根本认不出目录里有什么。一定要通过barman delete清理。
临时清出空间后,立刻检查 WAL 目录的大小,如果需要可以手工清理早期 WAL,但同样要谨慎,前面说了要用正确命令。最后再执行一次全量备份,把备份链重新立起来。
我个人的习惯是,备份盘容量监控的阈值设得比一般监控更保守,宁可多告警几次也不要等到“满盘再救火”。满盘救火的操作非常痛苦,而且你业务正在跑的时候,“救火”这个动作本身就是在给系统加风险。
最后再分享一个小技巧:我会在每个周五下午,从备份中随机挑一个实例做一次恢复演练,恢复到一台开发机上,跑一遍关键表的行数校验脚本,然后自动生成报告。Barman 的barman recover命令适合做成这条流水线的基础,如果演练过程中出现任何报错,说明备份链有问题,周末前还有时间修。用这个办法,我在过去两年里成功拦截过三次备份失效问题。备份恢复这件事,测试过、靠谱,心里才真正有底。