上一篇【第40篇】Standby数据库原理——理解PostgreSQL的高可用基础下一篇【第42篇】同步流复制与复制监控——确保数据零丢失理论讲完了现在动手。本文将手把手带你搭建一个完整的 PostgreSQL 流复制主备环境包括环境准备、主库配置、备库创建、复制验证和故障切换。一、环境准备1.1 服务器规划主备环境拓扑 ┌─────────────────────────────────────────────────────────────┐ │ │ │ 主库Primary 备库Standby │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ 192.168.1.10│ │ 192.168.1.20 │ │ │ │ PostgreSQL │ │ PostgreSQL │ │ │ │ Port: 5432 │←───复制───│ Port: 5432 │ │ │ │ 读写 │ │ 只读 │ │ │ └──────────────┘ └──────────────┘ │ │ │ │ 要求 │ │ - PostgreSQL 版本一致大版本必须相同 │ │ - 操作系统版本一致 │ │ - 时区配置一致 │ │ - 网络互通延迟 1ms │ └─────────────────────────────────────────────────────────────┘二、主库配置2.1 修改 postgresql.conf-- 在主库上执行以下配置-- 1. WAL 级别ALTERSYSTEMSETwal_levelreplica;-- 2. 最大 WAL 发送进程数ALTERSYSTEMSETmax_wal_senders10;-- 3. WAL 保留大小防止备库落后太多时 WAL 被删除ALTERSYSTEMSETwal_keep_size1GB;-- 4. 启用 WAL 归档强烈推荐ALTERSYSTEMSETarchive_modeon;ALTERSYSTEMSETarchive_commandcp %p /var/lib/postgresql/wal_archive/%f;-- 5. 热备模式主库也需要设置配置会传递给备库ALTERSYSTEMSEThot_standbyon;-- 6. 同步复制可选如果需要数据零丢失-- ALTER SYSTEM SET synchronous_standby_names standby1;-- ALTER SYSTEM SET synchronous_commit on;-- 7. 应用重连后生效SELECTpg_reload_conf();-- 8. 创建归档目录-- mkdir -p /var/lib/postgresql/wal_archive-- chown postgres:postgres /var/lib/postgresql/wal_archive2.2 创建复制用户-- 创建专用复制用户CREATEROLE repl_userWITHREPLICATIONLOGIN ENCRYPTED PASSWORDyour_secure_password;-- 验证用户创建SELECTrolname,rolreplicationFROMpg_rolesWHERErolnamerepl_user;2.3 配置 pg_hba.conf# 在主库的 pg_hba.conf 中添加允许备库连接进行复制# 编辑 /var/lib/postgresql/data/pg_hba.conf# 添加以下行# TYPE DATABASE USER ADDRESS METHODhostreplication repl_user192.168.1.20/32 md5# 或者允许整个网段开发环境# host replication repl_user 192.168.1.0/24 md5# 重新加载配置pg_ctl reload# 或在 psql 中SELECT pg_reload_conf();三、创建备库3.1 使用 pg_basebackup# 在备库服务器上执行# 1. 停止备库上的 PostgreSQL如果已安装sudosystemctl stop postgresql# 2. 清空数据目录rm-rf/var/lib/postgresql/14/main/*# 3. 使用 pg_basebackup 从主库复制数据# -h: 主库地址# -p: 主库端口# -U: 复制用户# -D: 备库数据目录# -X stream: 使用流复制传输 WAL# -P: 显示进度# -R: 自动创建 standby.signal 和 postgresql.auto.confPGPASSWORDyour_secure_passwordpg_basebackup\-h192.168.1.10\-p5432\-Urepl_user\-D/var/lib/postgresql/14/main\-Xstream\-P\-R# pg_basebackup -R 会自动创建# 1. standby.signal 文件标识这是备库# 2. postgresql.auto.conf包含 primary_conninfo 配置3.2 验证备库配置# 查看自动生成的配置cat/var/lib/postgresql/14/main/postgresql.auto.conf# 应该包含类似内容# primary_conninfo userrepl_user passwordyour_secure_password host192.168.1.10 port5432 sslmodeprefer sslcompression0 sslcertmodeallow sslsni1 gssencmodeprefer krbsrvnamepostgresql gssdelegation0 target_session_attrsany load_balance_hostsdisable# primary_slot_name # 查看 standby.signal 文件ls-la/var/lib/postgresql/14/main/standby.signal# 文件存在 这是备库# 设置文件权限chown-Rpostgres:postgres /var/lib/postgresql/14/mainchmod700/var/lib/postgresql/14/main3.3 启动备库# 启动备库sudosystemctl start postgresql# 查看备库日志确认处于恢复模式tail-f/var/log/postgresql/postgresql-14-main.log# 应该看到类似信息# LOG: entering standby mode# LOG: started streaming WAL from primary at 0/3000000 on timeline 1四、验证复制状态4.1 主库验证-- 在主库上执行SELECT*FROMpg_stat_replication;-- 输出示例-- pid | usesysid | usename | application_name | client_addr | state | ...-- 12345 | 16384 | repl_user | walreceiver | 192.168.1.20 | streaming | ...-- state streaming → 流复制正常运行4.2 备库验证-- 在备库上执行SELECTpg_is_in_recovery();-- 返回 true → 这是备库处于恢复模式-- 在备库上执行只读查询SELECTcount(*)FROMorders;-- 在备库上执行写操作应该报错INSERTINTOtest_tableVALUES(1);-- ERROR: cannot execute INSERT in a read-only transaction4.3 数据同步验证-- 在主库上创建测试数据-- 主库 psqlCREATETABLErepl_test(idINT,tsTIMESTAMPDEFAULTNOW());INSERTINTOrepl_testVALUES(1);SELECT*FROMrepl_test;-- 在备库上查询-- 备库 psql等待 1-2 秒后SELECT*FROMrepl_test;-- 应该看到 id1 的记录五、主备切换Failover5.1 计划内切换# 步骤1确保备库完全同步# 主库上执行SELECT pg_is_in_recovery();-- 返回false-- 备库上执行 SELECT pg_is_in_recovery();-- 返回trueSELECT pg_wal_lsn_diff((SELECT sent_lsn FROM pg_stat_replication LIMIT1), pg_last_wal_receive_lsn());-- 返回0表示完全同步# 步骤2停止主库sudosystemctl stop postgresql# 或在 psql 中执行SELECT pg_ctl_promote() 然后停止# 步骤3将备库提升为主库# 在备库上执行sudosystemctl stop postgresql# 方法A使用 pg_ctl promote推荐pg_ctl promote-D/var/lib/postgresql/14/main# 方法B创建 promote.signal 文件touch/var/lib/postgresql/14/main/promote.signalsudosystemctl start postgresql# PostgreSQL 启动时检测到 promote.signal → 提升为主库# 步骤4验证psql-cSELECT pg_is_in_recovery();# 返回 false → 已成功提升为主库5.2 将原主库重新作为备库加入# 在原主库现在已停止上执行# 1. 清空数据目录rm-rf/var/lib/postgresql/14/main/*# 2. 从新的主库原备库复制数据PGPASSWORDyour_secure_passwordpg_basebackup\-h192.168.1.20\-p5432\-Urepl_user\-D/var/lib/postgresql/14/main\-Xstream\-P\-R# 3. 启动sudosystemctl start postgresql# 4. 验证psql-cSELECT pg_is_in_recovery();# 返回 true → 成功成为新的备库六、配置 replication slot推荐-- 在主库上创建物理复制槽SELECTpg_create_physical_replication_slot(standby1_slot);-- 查看复制槽SELECT*FROMpg_replication_slots;-- slot_name | slot_type | active | restart_lsn-- standby1_slot | physical | t | 0/3000000-- 修改备库配置使用复制槽-- 在备库的 postgresql.auto.conf 中添加# primary_slot_name standby1_slot-- 好处-- 1. 即使备库断连很长时间主库也不会删除备库需要的 WAL-- 2. 防止备库重新连接时 WAL 已被回收导致需要全量同步七、自动故障切换自动故障切换工具推荐 ┌─────────────────────────────────────────────────────────────┐ │ 工具 │ 说明 │ ├───────────────────────┼─────────────────────────────────────┤ │ Patroni │ 最流行的自动 HA 方案推荐 │ │ (ZooKeeper/etcd) │ Python 编写支持 etcd/Consul │ ├───────────────────────┼─────────────────────────────────────┤ │ repmgr │ 轻量级复制管理器 │ │ (repmgrd) │ 支持 automatic failover │ ├───────────────────────┼─────────────────────────────────────┤ │ pgpool-II │ 连接池 内置 failover │ │ (Watchdog) │ 用 C 语言编写 │ └───────────────────────┴─────────────────────────────────────┘ 生产环境推荐 Patroni etcd HAProxy 组合方案八、常见问题排查Q1备库无法连接主库# 检查网络连通性telnet192.168.1.105432# 检查 pg_hba.conf 是否正确配置# 检查密码是否正确# 检查防火墙sudofirewall-cmd --list-allsudofirewall-cmd --add-port5432/tcp--permanentsudofirewall-cmd--reloadQ2备库落后太多-- 查看复制延迟SELECTclient_addr,state,sent_lsn,replay_lsn,pg_wal_lsn_diff(sent_lsn,replay_lsn)/1024/1024ASdelay_mbFROMpg_stat_replication;-- 原因分析-- 1. 网络带宽不足-- 2. 备库磁盘 I/O 太慢-- 3. 备库上有长时间运行的查询Hot Standby 冲突-- 4. 主库写入量突然增大-- 解决方案-- 1. 增大 wal_keep_size 防止 WAL 被删除-- 2. 使用复制槽-- 3. 减少备库上的查询负载Q3主库升级 PostgreSQL 版本后备库连不上PostgreSQL 不支持跨大版本的流复制 如果主库从 14 升级到 15备库也必须升级到 15。 流程 1. 先升级备库 2. 验证备库正常 3. 切换备库15变为主库 4. 原主库14停止重建为 15 的备库九、总结搭建流复制主备环境的核心步骤主库配置wal_levelreplica、创建复制用户、配置 pg_hba.conf备库创建pg_basebackup -R自动配置 standby.signal验证pg_stat_replication 确认流复制状态切换pg_ctl promote 提升备库为主库防护使用复制槽防止 WAL 丢失下一篇我们学习同步流复制与复制监控——确保数据零丢失的进阶配置。标签PostgreSQL、流复制、主备、pg_basebackup、Failover、高可用上一篇【第40篇】Standby数据库原理——理解PostgreSQL的高可用基础下一篇【第42篇】同步流复制与复制监控——确保数据零丢失