故障切换
主库故障、从库故障时的检测机制与切换流程详解。
Pigsty 的高可用系统支持两种切换模式:自动故障转移(Failover)和 主动切换(Switchover)。
故障检测
故障检测由 Patroni 和 Etcd 共同完成:
- 心跳机制:集群领导者(主库)持有 Etcd 租约,需要定期续期
- 租约超时:如果领导者在 TTL 时间内(默认 30s)未续期,租约释放
- 健康检查:HAProxy 通过 Patroni REST API 检测实例状态
检测时间线
0s 主库故障发生
↓
~10s Etcd 租约即将过期,Patroni 最后一次心跳失败
↓
~15s 租约过期,领导者锁释放
↓
~20s 从库 Patroni 检测到领导者空缺,开始竞选
↓
~25s 新领导者当选,从库提升为主库
↓
~30s HAProxy 检测到角色变化,流量切换完成
自动故障转移(Failover)
当主库因硬件故障、网络分区或进程崩溃而不可用时,系统自动执行故障转移。
流程详解
-
故障发生
- 主库 Patroni 进程崩溃或网络不可达
- Etcd 租约停止续期
-
领导者选举
- 租约过期后,所有候选从库开始竞争领导者锁
- 选举依据:数据完整性(LSN 位点最高者优先)
- 如果 LSN 差距超过
pg_rpo阈值,拒绝自动切换
-
主库提升
- 胜选从库执行
pg_ctl promote提升为主库 - 其他从库重新配置,指向新主库
- 胜选从库执行
-
流量切换
- Patroni REST API 返回新的角色信息
- HAProxy 将写流量路由到新主库
对业务的影响
- 写服务:不可用 15s ~ 30s,期间写请求失败或阻塞
- 读服务:短暂闪断后恢复,从库继续提供只读服务
主动切换(Switchover)
在计划维护、滚动升级等场景下,可以主动将主库角色转移到指定从库。
执行方式
# 使用 patronictl 执行切换
patronictl -c /pg/bin/patroni.yml switchover
# 或使用 Pigsty 封装的命令
pg switchover <cluster>
流程详解
-
发起切换
- 管理员通过 patronictl 或 API 发起 switchover 请求
- 指定目标从库(可选)
-
优雅降级
- 当前主库停止接受新的写入
- 等待所有进行中的事务完成
- 等待从库追上复制位点
-
角色交换
- 原主库降级为从库
- 目标从库提升为新主库
-
流量切换
- HAProxy 检测角色变化,更新路由
对业务的影响
- 写服务:短暂闪断(通常 < 5s)
- 读服务:几乎无感知
从库故障
从库故障的处理相对简单:
- HAProxy 检测:健康检查失败,将从库从后端池移除
- 流量转移:只读请求路由到其他健康从库
- 降级处理:如果所有从库都故障,只读流量由主库承担
对业务的影响
- 写服务:无影响
- 读服务:正在该从库上执行的查询中断,后续请求自动路由到其他节点
脑裂防护
脑裂是分布式系统最危险的场景:网络分区导致出现多个主库。
Pigsty 的防护机制
-
DCS 仲裁:领导者锁由 Etcd 集群统一管理,网络分区时只有能访问多数派的节点才能持有锁
-
Failsafe 模式:Patroni 默认启用
failsafe_mode,当无法联系 DCS 时,主库降级为只读 -
看门狗(可选):启用硬件看门狗后,失去 DCS 联系的主库会被强制重启
patroni_watchdog_mode: automatic # 或 required -
VIP 漂移:vip-manager 从 Etcd 获取领导者信息,只有真正的主库才能绑定 VIP
故障恢复
原主库恢复
当故障的原主库重新上线时:
- 角色降级:原主库发现已有新领导者,自动降级为从库
- 数据同步:如果数据差异在
pg_rpo范围内,使用pg_rewind快速同步 - 重新加入:作为从库重新加入集群
手动干预场景
以下情况可能需要人工干预:
- 数据差异超过
pg_rpo阈值 - 时间线分叉严重
- 需要从备份恢复数据
# 查看集群状态
patronictl -c /pg/bin/patroni.yml list
# 手动重新初始化成员
patronictl -c /pg/bin/patroni.yml reinit <cluster> <member>
最佳实践
-
至少三节点:生产环境建议 1 主 2 从,确保故障切换有足够候选
-
跨机架/机房部署:避免单点故障影响整个集群
-
监控告警:配置复制延迟、连接数等告警
-
定期演练:通过 switchover 验证故障切换流程
-
备份策略:HA 不能替代备份,配合 PITR 应对逻辑错误