Postgres数据库管理-主备高可用搭建步骤V1

📅 发布时间:2026/7/8 17:14:54 👁️ 浏览次数:
Postgres数据库管理-主备高可用搭建步骤V1
1 PG主备高可用搭建1 准备工作主库配置是整个主备同步的基石这一步配置对了后面就顺风顺水。我把它拆解成几个清晰的步骤你跟着操作就行关键参数我都会解释清楚为什么这么设。先配置pg_hba.conf这个文件管“谁能连怎么连”。我们需要添加规则允许备库服务器以复制用户的身份连接过来。# 进入挂载的数据目录cd pgdatavi pg_hba.conf在文件末尾添加如下两行host replication repuser 172.27.1.11/32 md5host replication repuser 172.27.1.12/32 md5这两行的意思是允许来自IP 172.27.1.11 和 172.27.1.12 的主机使用 repuser 这个数据库用户通过密码认证md5的方式发起复制连接。这里把主库自己的IP也加进去是因为后面做备份或者某些管理操作时也可能需要。一个重要的经验为了让未来主备切换更平滑我习惯把主备库的pg_hba.conf配成一样的都允许对方的IP连接。接下来是重头戏postgresql.conf它控制着数据库的行为。我们需要修改几个关键参数来启用流复制。找到并修改以下参数如果被注释了就取消注释并修改值listen_addresses * # 监听所有IP地址让备库能连过来wal_level replica # WAL日志级别设为replica才能支持流复制archive_mode on # 开启归档模式虽然流复制不一定需要但建议打开archive_command /bin/date # 一个“伪归档”命令先占位以后可改成真实归档脚本max_wal_senders 10 # 最大WAL发送进程数一个备库通常消耗一个wal_keep_segments 64 # 在主库pg_wal目录保留的WAL日志文件最小数量防止备库落后太多时追不上hot_standby on # 在备库上允许只读查询这个主库也打开max_connections 1000 # 最大连接数根据业务调整这里重点说下 wal_level 和 wal_keep_segments。wal_level 有 minimal、replica、logical 三级。minimal 只记录崩溃恢复所需的最少信息不支持复制。我们要做流复制至少要设为 replica。如果未来想玩逻辑复制按表同步那就要升级到 logical。wal_keep_segments 是个“安全垫”假设备库网络中断了一会儿重启后如果主库的WAL日志还没被覆盖保留了64个文件备库就能接着同步否则就得从头做基准备份了。对于繁忙的生产库这个值可以设得更大比如256或512。2 创建专用的复制用户最后一步在主库上创建一个专门用于数据复制的用户。这个用户不需要创建表的权限但必须有REPLICATION权限。# 创建复制用户CREATE ROLE repuser WITH LOGIN REPLICATION ENCRYPTED PASSWORD repuser;执行\du命令应该能看到repuser用户的属性里包含了Replication。至此主库就配置完毕了它已经准备好接受来自备库的连接并传输数据。3. 备库配置实战从零搭建一个同步副本备库的配置过程有点像给新手机做数据迁移。核心思想是先从一个“健康”的主库那里拿到一份完整的数据快照基础备份然后告诉备库“以后就跟着这个主库混它有什么新动静你立刻学”。这个过程主要依赖一个强大的工具pg_basebackup。在备节点slave创建/backup目录pg_basebackup -h 172.27.1.11 -U repuser -Fp -Xs -P -v-R-D /backup输入密码 repuser 后你会看到进度条开始滚动。我来拆解一下这几个参数-h 172.27.1.11主库的IP地址。-U repuser使用我们刚才创建的复制用户。-Fp备份格式为 plain即原样输出文件布局恢复时直接可用。-Xs使用 stream 方式并行传输WAL日志。这是生产环境推荐的做法它会在备份期间持续从主库流式接收WAL确保备份结束时数据就是最新的没有缺口。-P显示进度让你心里有数。-v输出详细日志方便排错。-R这个参数很重要它会自动在备份目录里生成一个standby.signal 文件PostgreSQL 12或 recovery.conf 文件PostgreSQL 11里面包含了连接主库的信息省去了我们手动创建的步骤。-D /backup指定备份数据存放的目标路径。命令成功执行后主库的完整数据就已经躺在备库服务器的 ./backup 目录里了。4 配置备库并启动然后将刚才的备份数据移动到pgdata目录# 删除可能存在的空pgdata目录rm -rf pgdata# 将备份数据重命名为pgdatamv backup pgdata由于我们使用了-R参数在pgdata目录下已经生成了一个standby.signal文件PG12或recovery.conf文件PG11。对于PostgreSQL 11我们检查一下recovery.conf文件cd pgdatacat recovery.conf内容应该类似于standby_mode onprimary_conninfo userrepuser passwordrepuser host172.27.1.11 port5432 sslmodeprefer sslcompression0 gssencmodeprefer krbsrvnamepostgres target_session_attrsany启动后备库会自动读取recovery.conf或standby.signal进入恢复模式连接主库并开始持续应用WAL日志。这时备库会处于“只读”状态你可以查询数据但不能修改。5. 验证与监控确保同步健康进行配置完不验证等于白干。我们需要一些方法来确认主备同步是否真的建立起来了并且运行得是否健康。PostgreSQL提供了非常丰富的系统视图和函数来帮我们做这件事。在主库上查看发送进程最直接的方法就是去主库上看看有没有WAL发送进程在给我们的备库干活。连接到主库数据库执行以下查询SELECT usename, application_name, client_addr, state, sync_state, write_lag, flush_lag, replay_lagFROMpg_stat_replication;如果同步配置成功你会看到一条记录其中 client_addr 就是备库的IP地址。state 字段应该是 streaming表示流式传输正常。sync_state 字段表示同步模式如果是 async 就是异步复制如果是 sync 就是同步复制我们当前是异步。最有用的是后面三个 *_lag 字段它们分别表示备库在“接收写入”、“刷入磁盘”、“重放应用”这三个环节落后主库的时间。在异步复制下replay_lag 是衡量备库延迟的关键指标理想情况下应该在毫秒级。在备库上确认自身角色在备库上我们可以通过一个简单的函数来确认自己是不是备库SELECT pg_is_in_recovery();如果返回t(true)恭喜你它确实是一个正在恢复即作为备库的实例。返回f(false) 则表示它是主库。这个检查在写脚本做自动化故障切换时特别有用。模拟数据同步测试-- 在主库执行CREATE TABLE test_sync (id serial PRIMARY KEY, data text, created_at timestamptz DEFAULT now());INSERT INTO test_sync (data) VALUES (Hello from Master!);然后立刻切换到备库的连接执行查询SELECT * FROM test_sync;2 故障切换演练配置好主备同步就像是给数据库上了个保险。但保险能不能在出事时真的赔钱还得看理赔流程顺不顺畅。故障切换就是这个“理赔流程”。我们绝不能等到生产环境主库真宕机了再去翻手册必须提前演练形成肌肉记忆。下面我来模拟一次完整的主库故障并手动将备库提升为新主库。1 模拟主库故障切换备库为新的主库现在应用程序连接到主库5432端口的请求都会失败。我们的目标是让业务尽快恢复方法就是将备库“扶正”。连接到备库服务器。重要在提升之前请确保旧主库不会再启动。如果旧主库因为网络分区等原因还“活着”并且它认为自己还是主库就会发生“脑裂”两个主库同时写入这是灾难性的。在备库上我们有两种方式将其提升为主库方法一使用pg_ctl命令推荐# 切换到postgres用户Alpine镜像默认是postgres用户su - postgres# 执行提升命令pg_ctl promote -D $PGDATA$PGDATA是环境变量指向/var/lib/postgresql/data。执行成功后你会看到类似 “server promoted” 的提示。方法二创建触发文件PostgreSQL会监视数据目录下是否存在一个特定的“触发文件”。如果存在备库就会将自己提升为主库。我们可以在宿主机上操作# 在备库的数据目录下创建一个名为 failover.trigger 的文件touch /var/lib/postgresql/data/两种方法任选其一。提升完成后再次在备库现在已经是新主库了上执行SELECT pg_is_in_recovery();应该返回 f 了。同时检查recovery.conf 或 standby.signal 文件它们会被重命名如 recovery.done表示恢复模式已结束。恢复旧主库并重构同步关系在旧主库服务器上如果数据目录 pgdata 还在先备份一下以防万一然后清空它。因为它的数据已经落后于新主库且可能有不一致不能直接用了。cd pg-mastermv pgdata pgdata_old_bakmkdir pgdata像配置新备库一样使用 pg_basebackup 从新主库现在是 172.27.1.12拉取一份全新的基础备份到旧主库的 pgdata 目录。注意命令中的IP要改pg_basebackup -h 172.27.1.12 -U repuser -Fp -Xs -P -v -R -D ./pgdata确保新的 recovery.conf 文件里的 primary_conninfo 指向的是新主库 172.27.1.12。它现在就是以新备库的身份运行了。去新主库上执行 SELECT * FROM pg_stat_replication;应该能看到旧主库的IP作为客户端连接过来状态是 streaming。至此一次完整的手动故障切换演练就完成了。角色发生了互换原来的备库成了主库原来的主库修复后成了新的备库。这个过程看似步骤不少但通过脚本化完全可以做到分钟级甚至秒级完成切换将业务中断时间降到最低3 进阶配置与生产环境考量基础的异步流复制搭建好了也能手动切换了但这对于要求苛刻的生产环境可能还不够。下面我分享几个进阶配置点帮你把主备同步做得更稳、更强。同步复制 vs 异步复制我们之前配置的是异步复制。它的优点是性能好主库事务提交成功就立刻返回给客户端不用等备库确认。缺点是如果主库在事务提交后、WAL日志发送到备库前崩溃可能会导致数据丢失尽管窗口期极短。对于金融、交易等零数据丢失场景可以考虑同步复制。配置很简单在主库的 postgresql.conf 中设置synchronous_commit onsynchronous_standby_names FIRST 1 (slave1)并在备库的 recovery.conf 的 primary_conninfo 中加上 application_nameslave1。这样主库每次提交事务时都会等待至少一个备库slave1写入并刷盘确认后才向客户端返回成功。代价是主库的写延迟会增加等于增加了网络往返时间。你需要根据业务对数据一致性和性能的权衡来做选择。也可以配置多个备库采用 FIRST N 或 ANY N 等灵活策略。4 监控与告警不能等用户投诉了才发现备库不同步。必须建立监控。除了前面提到的 pg_stat_replication 视图还可以监控备库延迟SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS delay_bytes FROM pg_stat_replication; 可以计算出延迟的字节数。结合WAL日志生成速度可以估算延迟时间。备库连接状态定期检查 pg_stat_replication 中是否有记录state 是否为 streaming。备库是否可读定期在备库执行一个简单查询如 SELECT 1;确保其只读服务正常。将这些指标接入到 Prometheus Grafana 或 Zabbix 等监控系统中并设置告警规则。例如当replay_lag超过10秒或者备库连接断开超过1分钟就立即发送告警通知DBA。5 归档与PITR时间点恢复流复制保护的是“现在”的数据。如果你想恢复到“昨天下午3点”的状态比如误删了一张表就需要WAL归档和PITR。归档修改主库 postgresql.conf 中的 archive_command将写满的WAL日志文件复制到安全的存储上比如NFS、S3或另一台服务器。例如archive_command cp %p /mnt/wal_archive/%f。PITR当需要恢复时用一个基础备份可以用 pg_basebackup 定期做再加上归档的WAL日志就可以将数据库恢复到备份后的任意时间点。这是流复制之外的第二道重要防线一定要配置。主备同步不是“配置完就一劳永逸”的事情。它需要前期的精心设计需要定期的监控和维护更需要像故障切换这样的实战演练。把这些都做到位你的数据库才能真正拥有应对故障的韧性。6 standby.signal 文件的作用standby.signal 是 PostgreSQL 数据库中的一个信号文件用于控制数据库实例的状态转换。当该文件存在于 PostgreSQL 的数据目录data_directory中时数据库会进入“standby mode”备用模式通常用于流复制或逻辑复制场景。以下是关于该文件的详细信息文件功能触发备用模式当standby.signal文件存在时PostgreSQL 实例会以备用服务器standby模式启动自动从主服务器primary接收 WALWrite-Ahead Log日志并应用。与recovery.signal的区别在 PostgreSQL 12 及更高版本中standby.signal和recovery.signal被明确区分。standby.signal表示实例为长期运行的备用服务器而recovery.signal表示实例处于一次性恢复状态如 PITR。使用方法创建文件在 PostgreSQL 的数据目录中创建空文件standby.signaltouch $PGDATA/standby.signal配置复制参数需在postgresql.conf中配置流复制相关参数例如primary_conninfo hostprimary_server userreplication passwordxxx port5432 restore_command cp /path/to/archive/%f %p重启实例文件创建后重启 PostgreSQL 实例以进入备用模式pg_ctl restart -D $PGDATA注意事项文件权限确保standby.signal文件对 PostgreSQL 运行用户可读。版本兼容性PostgreSQL 10 及更早版本使用recovery.conf文件配置备用模式而非standby.signal。自动删除当备用服务器提升为主服务器时通过pg_promote()或pg_ctl promotestandby.signal文件会被自动删除。验证备用状态通过查询数据库状态确认是否成功进入备用模式SELECT pg_is_in_recovery();返回true表示当前为备用服务器。故障排查日志检查若备用模式未生效查看 PostgreSQL 日志文件logfile排查错误。文件冲突确保数据目录中不存在recovery.signal或旧的recovery.conf文件仅限 PostgreSQL 12。通过以上步骤可以正确配置并使用standby.signal文件