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):
| 维度 | Patroni | repmgr | pg_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),仅供参考