3. 跨地域流复制部署实战

跨地域流复制与同机房流复制最大的差别不在命令本身,而在于“距离”带来的三个约束:网络往返时延(RTT)会直接抬高同步提交的等待时间,跨地域链路带宽有限且可能计费,异地备库一旦落后,追赶所需的 WAL 传输量会成倍放大。因此本节围绕一条真实可落地的部署链路展开:先配置主库,再搭建异地备库,然后用复制槽把 WAL 保留责任绑定到备库,最后用延迟与带宽数据判断这套架构是否满足 RPO/RTO 目标。

一、主库配置:先确定复制模式与 WAL 保留策略

主库侧的核心参数集中在 postgresql.conf。跨地域场景下,是否开启同步复制决定了业务写入是否要等待异地确认。若 RPO 要求接近 0,可考虑同步复制,但必须接受 RTT 带来的提交延迟;若业务对延迟敏感,则采用异步复制,用复制槽保证 WAL 不被过早回收。

# postgresql.conf(主库,示例参数)
listen_addresses = '*'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1GB
synchronous_commit = on          # 异步复制时保持 on 即可
synchronous_standby_names = ''   # 需要同步复制时再填写备库名
archive_mode = on
archive_command = 'cp %p /data/pg_archive/%f'

其中 wal_level=replica 是流复制的最低要求;max_wal_senders 要大于备库数量加监控连接数;wal_keep_size 是复制槽之外的兜底保留量。跨地域链路抖动概率更高,建议同时开启归档,避免备库长时间断连后主库已回收所需 WAL。

接着配置访问控制。在 pg_hba.conf 中为异地备库所在网段开放复制连接:

# pg_hba.conf
host    replication     repl_user    10.20.30.0/24    scram-sha-256

创建专用复制账号并授权:

CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'StrongPass!2024';

修改完成后执行 SELECT pg_reload_conf(); 使配置生效,并用 SHOW wal_level; 确认参数已加载。

二、异地备库搭建:从基础备份到流复制启动

异地备库搭建推荐使用 pg_basebackup,它会自动生成 standby.signal 并写入连接信息。假设主库地址为 10.10.1.10,备库数据目录为 /data/pgdata:

pg_basebackup -h 10.10.1.10 -p 5432 -U repl_user \
  -D /data/pgdata -Fp -Xs -P -R \
  --slot=slot_beijing

参数含义:-Fp 使用普通文件格式,-Xs 在备份过程中同时流式传输 WAL,-R 自动生成 postgresql.auto.conf 中的 primary_conninfo 与 primary_slot_name。执行完成后检查备库配置:

# postgresql.auto.conf(备库自动生成)
primary_conninfo = 'host=10.10.1.10 port=5432 user=repl_user password=StrongPass!2024'
primary_slot_name = 'slot_beijing'

启动备库后,在主库执行 SELECT * FROM pg_stat_replication;,应看到 state=streaming、sync_state=async(或 sync)。在备库执行 SELECT pg_is_in_recovery(); 应返回 t,说明已处于只读恢复状态。

主库(华东 10.10.1.10) wal_level = replica max_wal_senders = 10 pg_hba.conf replication repl_user archive_mode = on WAL 归档兜底 复制槽 slot_beijing 保留备库未确认 WAL 异地备库(华北 10.20.30.20) pg_basebackup -R 自动生成 standby.signal primary_conninfo host=10.10.1.10 primary_slot_name slot_beijing pg_is_in_recovery() = t 只读恢复状态 跨地域链路 RTT ≈ 30 ms(示例) 带宽 ≈ 100 Mbps WAL 流式传输 TCP 5432 延迟↑ → 同步提交等待↑ 带宽↓ → 追赶时间↑ WAL WAL 备库 LSN 确认 → 主库推进复制槽 restart_lsn 观察点:pg_stat_replication state / sent_lsn / replay_lsn 观察点:pg_stat_replication_slots pg_wal_lsn_diff 计算延迟字节

三、复制槽管理:把 WAL 保留责任绑定到备库

复制槽是跨地域部署中最容易被忽视、也最容易引发磁盘告警的组件。它的作用是让主库知道“这个备库还没消费到哪个 LSN”,从而不回收对应 WAL。创建方式有两种:

-- 物理复制槽(推荐,与 pg_basebackup --slot 配合)
SELECT * FROM pg_create_physical_replication_slot('slot_beijing');

-- 查看所有复制槽状态
SELECT slot_name, slot_type, active, restart_lsn,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained
FROM pg_replication_slots;

关键判断指标是 retained:它表示该槽当前保留了多少 WAL。若备库断连数小时,这个值会持续增长。跨地域场景建议设置监控阈值,例如保留量超过 20GB 或超过 wal_keep_size 的 5 倍时告警。若确认备库已废弃,必须及时删除槽,否则主库 WAL 会无限堆积:

SELECT pg_drop_replication_slot('slot_beijing');

四、网络延迟与带宽评估:用数据判断架构是否可行

延迟评估的核心是 RTT 与同步提交的关系。异步复制下,RTT 只影响备库落后量;同步复制下,每次事务提交至少要等待一个 RTT。以示例 RTT=30ms 计算,若业务 QPS 为 500 且全部为同步提交,理论最小提交延迟约 30ms,吞吐上限约 33 事务/秒/连接,必须靠连接并发或组提交缓解。

带宽评估则要估算 WAL 生成速率。假设主库峰值 WAL 生成速率为 20MB/s,跨地域链路可用带宽为 100Mbps(约 12.5MB/s),则链路无法实时跟上,备库会持续落后。此时需要:提高带宽、降低 WAL 生成(如减少全页写、调整 checkpoint_timeout)、或接受异步复制并预留追赶窗口。

实际观测可用以下查询:

-- 主库:查看备库延迟字节
SELECT client_addr, state, sync_state,
       pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replay_lag_bytes,
       pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn)   AS send_lag_bytes
FROM pg_stat_replication;

-- 备库:查看最近一次 WAL 接收时间
SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(),
       now() - pg_last_xact_replay_timestamp() AS replay_delay;

判断标准建议:replay_lag_bytes 持续小于 64MB 且 replay_delay 小于 5 秒,可认为链路健康;若 send_lag_bytes 远大于 replay_lag_bytes,说明瓶颈在网络而非备库回放;若两者都大,则需同时检查带宽与备库 I/O。

跨地域部署建议把 synchronous_commit 设为 remote_write 而非 on,可在保证 WAL 已发送到异地的前提下减少一次本地刷盘等待;若 RPO 允许秒级,直接使用异步复制加复制槽是更稳妥的选择。
复制槽不会自动清理。备库下线、重建或改名后,务必核对 pg_replication_slots 中是否存在 active=false 的残留槽,否则主库磁盘可能被 WAL 撑满,进而触发主库不可写。

把以上四步串起来,一套跨地域流复制的可运行闭环就形成了:主库开启归档与复制参数,异地备库通过 pg_basebackup -R 建立并进入流复制,复制槽保证 WAL 保留责任明确,延迟与带宽指标则用于持续判断这套架构是否仍满足业务 RPO/RTO。部署完成后,应把 pg_stat_replication、pg_replication_slots 和备库回放延迟纳入常态化监控,而不是只在割接当天检查一次。