PostgreSQL 高可用:3 种故障转移方案怎么选?

PostgreSQL 高可用:3 种故障转移方案怎么选?

【免费下载链接】awesome-postgresA curated list of awesome PostgreSQL software, libraries, tools and resources, inspired by awesome-mysql项目地址: https://gitcode.com/gh_mirrors/aw/awesome-postgres

本文解决一个问题:PostgreSQL 主库宕机后,如何把流量以最小停机切到备库。以 awesome-postgres 生态里的故障转移工具为参照,讲清工具选型对比、Patroni 自动切换全流程、手动主从切换清单,以及监控与演练节奏。面向 DBA 与后端开发者,读完能选对工具并跑通一次真实切换演练。

主库宕机时的业务代价

凌晨三点,主库进程挂掉或者磁盘写满。若备库没有被提升,所有写请求堆在连接池里,事务日志停止推进,上游服务开始成批返回 5xx——应用已经"半死"。宕机时间每多一分钟,投诉与 SLA 赔付就多一分。唯一的出路是把流量切到健康备库:用哪个工具、如何判定主库真的死了、怎么避免两个节点都自认为是主库(脑裂),是本文逐一拆解的问题。

工具选型:Patroni / repmgr / pg_auto_failover 对比

awesome-postgres 的 High-Availability 板块中,三者最具代表性(完整工具清单见 README.md):

维度Patronirepmgrpg_auto_failover
共识组件依赖依赖 etcd / Consul / ZooKeeper 等 DCS无,用独立管理库无,内置监控服务
自动切换能力自动,DCS 锁防脑裂repmgrd 自动监控,需调参自动,由服务进程监控
部署复杂度较高,需先搭 DCS 集群中等,命令直观低,装扩展加服务即可
适用场景K8s / 多节点生产集群要求流程可控可审计的团队配置最少的小中集群

结论:环境里已有 etcd 或跑在 K8s 上,选 Patroni,其 DCS 锁是防脑裂最可靠的机制;不能接受任何外部组件,从 pg_auto_failover 起步,全程只需要一个监控服务;repmgr 适合"手动为主、自动兜底"的团队,命令集最透明,切换过程便于理解和审计。

Patroni 自动故障切换的五步走读

第一步 故障发生:怎么判断

主库停止接受连接、WAL 生成停止。别立刻下结论——瞬时网络分区看起来也一样,判定条件是进程或端口不可达,并等健康检查确认。

第二步 健康检查判定:ttl 与 loop_wait 怎么设

Patroni 主库在 DCS 里持有 leader 键,需在ttl(默认 30 秒)内刷新,检查周期由loop_wait控制。判定条件:超过一个loop_wait周期仍未刷新,其余节点判定主库失联。业务敏感时把loop_wait缩到 10 秒,代价是抖动期误报增多。

第三步 提升备库:锁决定谁上位

备库节点竞争 DCS 的 master 锁,先拿到锁的才执行 promote。判定条件:成功拿锁,且相对旧主 WAL 位点(LSN)的复制延迟在阈值内;落后的节点主动放弃本轮。

第四步 客户端重连

应用侧探测到连接错误后自动重试,通过集群名或连接池解析新主地址,配合 PgBouncer 可让切换对应用透明。判定条件:新主pg_is_in_recovery()返回 false,读写冒烟通过。

第五步 原主回归

旧主恢复后由 Patroni 以备库模式重启,回放缺失的 WAL。判定条件:旧主启动后处于 recovery 状态,与新主的复制恢复正常且延迟追平。

Patroni 关键配置与检查命令:

postgresql: parameters: synchronous_commit: remote_apply restapi: listen: 0.0.0.0:8008 etcd3: hosts: etcd1.internal:2379,etcd2.internal:2379

切换后执行一条命令确认各节点角色:

patronictl list

手动主从切换清单:切换前 / 中 / 后

没有自动化工具的团队,按以下清单推进切换:

切换前

  • 确认主库无法恢复,记录时间与故障现象
  • 核对备库pg_is_in_recovery()为 true,复制延迟在可接受范围
  • 冻结应用写入(停连接池或置只读),降低不一致风险
  • 记录备库当前 WAL 位点(LSN),便于事后比对

切换中

  • 在备库执行提升为主库(recovery.signal + pg_promote,或 repmgr standby promote)
  • 提升后确认可读可写
  • 把客户端连接串 / VIP / DNS 指向新主

切换后

  • 恢复应用流量,做读写冒烟测试
  • 原主重建为新主的备库,验证复制追平
  • 更新监控对象与告警规则
  • 归档切换日志与 LSN 记录,留作审计

三个常见坑:脑裂、数据不一致、连接失败

脑裂(两个主库同时接受写入)

  • 现象:新旧主库事务序列各走各的,应用侧数据"消失"。
  • 根因:网络分区让旧主以为仍存活,备库又被提升,缺乏锁阻止双主。
  • 对策:依赖 DCS 分布式锁,或人工确认仲裁后再提升;核心业务用同步复制保证备库数据完整。

数据不一致(新主丢最近事务)

  • 现象:切换后查询最近几条写入查不到。
  • 根因:被提升的备库 LSN 落后旧主,异步复制的最后几个事务丢失。
  • 对策:核心表开同步复制;日常监控复制延迟超 5 秒即告警;关键数据切换前先核对。

应用连接失败(切换后不恢复)

  • 现象:新主库正常,应用却持续抛连接错误。
  • 根因:应用写死旧主地址,连接池挂着失效连接,且未配置自动重连。
  • 对策:PgBouncer 前置让应用透明重连;应用侧开启带退避的重试;服务发现指向集群名而非固定 IP。

监控指标与演练节奏

指标含义阈值建议
复制延迟备库 WAL 回放落后量超 5 秒告警,超 30 秒红色
WAL 生成速率主库每秒 WAL 产出偏离基线 3 倍排查写入异常
主库连接探测端口与健康检查成功率连续 3 次失败即告警
WAL 磁盘剩余空间归档与预写日志容量剩余低于 20% 告警
缓冲命中 / 内存buffer cache 命中率低于 90% 需排查

演练节奏:

  • 月度:计划内窗口做一次主从切换演练,验证应用自动重连链路
  • 季度:kill 主库模拟真实故障,验证自动故障切换的耗时与正确性
  • 年度:全流程灾难恢复演练,含原主回归与数据校验

收个尾

故障转移工具只是高可用的一半,另一半是监控数据与演练记录。先选一个与团队运维水平匹配的工具,在测试环境跑通第一次切换。让"切换"成为可验证的流程,下一次真实故障才会只是告警日志里的一行记录。

⚠️ 生产变更提醒:任何故障转移方案先在测试环境验证,并在业务低峰期执行;动手前备好回滚预案(VIP 回切、连接串回退、原主恢复步骤)。

【免费下载链接】awesome-postgresA curated list of awesome PostgreSQL software, libraries, tools and resources, inspired by awesome-mysql项目地址: https://gitcode.com/gh_mirrors/aw/awesome-postgres

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考