PostgreSQL 流复制 + 自动故障转移
症状
目标:使用流复制为 PostgreSQL 搭建 hot standby,并加入 Patroni/repmgr 实现自动故障转移。
1. 在主库上设置 WAL 和连接参数
对于流复制,wal_level 至少须为 'replica'。max_wal_senders 必须覆盖副本数 + 备份连接数,并须通过 wal_keep_size 或复制槽防止 WAL 被过早删除。这些更改需要重启。
PostgreSQL
ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM SET max_wal_senders = 10;
ALTER SYSTEM SET max_replication_slots = 10;
ALTER SYSTEM SET hot_standby = on;
-- To apply the postgresql.conf change:
-- systemctl restart postgresql2. 定义复制角色和 pg_hba 访问
创建一个带 REPLICATION 属性的角色,供备库连接使用。在 pg_hba.conf 中添加一行,允许从备库 IP 访问 'replication' 数据库,并用 pg_reload_conf() 重新加载。
PostgreSQL
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secret';
-- Add to pg_hba.conf:
-- host replication replicator 10.0.0.20/32 scram-sha-256
SELECT pg_reload_conf();3. 在主库上创建持久复制槽
物理复制槽可防止主库在备库落后时删除所需的 WAL;用复制槽管理比 wal_keep_size 更安全。我们将在备库配置中使用该槽名。
PostgreSQL
SELECT pg_create_physical_replication_slot('standby1_slot');
SELECT slot_name, active, restart_lsn FROM pg_replication_slots;4. 在备库服务器上用 pg_basebackup 做基础备份
在备库数据目录为空的情况下,从主库获取完整副本。-R 参数会自动写入 standby.signal 文件和 primary_conninfo;-C 还可以创建复制槽。槽名通过 -S 传入。
PostgreSQL
pg_basebackup -h 10.0.0.10 -U replicator -D /var/lib/pgsql/data \
-R -X stream -S standby1_slot -P -v5. 验证 primary_conninfo 和 hot_standby,启动备库
检查 -R 写入的 postgresql.auto.conf 中的 primary_conninfo(host、user、slot);standby.signal 文件的存在决定备库模式。hot_standby=on 时备库接受只读查询。启动服务。
PostgreSQL
-- Expected in postgresql.auto.conf:
-- primary_conninfo = 'host=10.0.0.10 user=replicator password=secret'
-- primary_slot_name = 'standby1_slot'
-- systemctl start postgresql
SELECT pg_is_in_recovery(); -- should return true on the standby6. 从主库监控复制延迟
在主库上,pg_stat_replication 显示每个备库的已发送/已重放 LSN 和延迟。write/flush/replay lag 应保持较小;若使用同步副本,sync_state 为 'sync'。
PostgreSQL
SELECT client_addr, state, sync_state,
pg_wal_lsn_diff(sent_lsn, replay_lsn) AS replay_lag_bytes,
write_lag, flush_lag, replay_lag
FROM pg_stat_replication;7. 加入 Patroni 或 repmgr 实现自动故障转移
单纯的流复制需要手动 promote。自动故障转移需要集群管理器:Patroni(基于 etcd/Consul 的领导者选举 + 自动 promote)或 repmgr(由 repmgrd 监控/故障转移)。在应用端,用 HAProxy/pgBouncer 提供单一端点。若需要手动 promote:pg_ctl promote。promote 之前,务必确认旧主库确实已停止且应用无法写入(脑裂风险)。将旧主库作为新主库的备库重新加入需要 pg_rewind;为此必须启用 wal_log_hints = on 或数据校验和。
PostgreSQL
-- Manual promote (if there is no cluster manager):
pg_ctl promote -D /var/lib/pgsql/data
-- or via SQL:
SELECT pg_promote();
-- With Patroni: patronictl -c /etc/patroni.yml switchover mycluster