33.3 自动故障转移的保护条件
自动故障转移的价值,是在预先证明过的条件内缩短决策时间;它不是在信息不足时替人 猜测。一个安全状态机应当宁可暂时没有可写主库,也不接受两个相互冲突的写 authority。
简化后的 Patroni 路径:
ttl、loop_wait 与 retry_timeout 会影响探测和选举节奏,但端到端 RTO 还包括
PostgreSQL 停止/恢复、DCS 延迟、候选 replay、代理健康检查、连接重建和客户端重试。
33.3.1 候选健康、数据风险与多数判断
候选先通过资格门
候选至少需要:
| 条件 | 目的 | 证据 |
|---|---|---|
| Patroni REST 可达 | 能参与管理与健康检查 | exact endpoint/status |
| 同 system identifier | 属于同一物理 lineage | pg_control_system() |
| WAL/timeline 可接受 | 不跳回旧分支 | LSN、history、check_timeline |
| lag 在策略内 | 控制异步数据风险 | pg_stat_replication 与 policy |
nofailover=false |
未被运维策略排除 | Patroni tags |
| replay 未异常暂停 | promotion 后能完成 recovery | recovery/receiver state |
| required watchdog 可用 | 满足本节点 leader 前提 | Patroni/watchdog status |
| 同步模式条件满足 | 遵守 sync/quorum policy | DCS sync state |
“候选服务可连”没有覆盖这些条件。一个被刻意延迟 30 分钟的 reporting replica 可能非常 健康,却绝不能自动成为业务主库。
三种“多数”不要混为一谈
三节点 PostgreSQL 加单节点 etcd,并不会因为“数据库还有 2/3”就拥有 DCS 多数; 三节点 etcd 加两节点 PostgreSQL,也不会自动使 PostgreSQL 写入成为多数派复制。DCS 负责协调 leader authority,WAL durability 由 PostgreSQL replication mode 决定。
生产设计需要分别画失败域:
异步可用性换取数据风险
默认异步模式允许 primary 在副本未确认时提交。故障后提升某个满足最低健康条件的
standby,未复制到它的事务会留在旧分支。maximum_lag_on_failover 限制候选在最近
观测时的 WAL gap,却不覆盖观测后到故障间的新 WAL。
所以报告应写:
而不是只写 RPO < 1MB。WAL 字节不是业务订单数,unknown 也不等于丢失。
同步模式能收紧正常单故障的数据风险,但也有可用性和复合故障边界。切换报告仍应验证 业务 identity,不把配置名当作结果。
自动选择不等于随机选择
Patroni 按当前资格与状态参与 leader race;操作者不应从成员列表顺序推断赢家。本章
正式 run 的两个 replica 都合格,实际 pg-test-3 提升。正确验收是:
如果业务要求指定节点,使用 planned switchover 或明确 tags/拓扑策略,不能把自动选举 伪装成固定候选。
33.3.2 fencing 旧主与防止双写
fence 的目标是消除旧 authority
旧主围栏的验收谓词:
或者在特殊设计中:
第二种更难证明,因为必须覆盖所有客户端、job、CDC、消息和外部副作用。数据库 HA 通常优先选择第一种:让 PostgreSQL 停止、只读、失去存储或节点断电。
围栏层次
| fence | 能证明 | 主要盲点 |
|---|---|---|
| PostgreSQL clean stop | postmaster 不再写 | I/O hang 时可能无法完成 |
| Patroni demote/stop | 角色管理与数据库按协议停止 | 控制进程自身可能失效 |
| watchdog reset | Patroni 未续喂时节点重启 | 设备/权限/超时配置必须真实可用 |
| BMC/cloud power off | 主机失去计算能力 | 控制面状态延迟、自动重启策略 |
| storage detach/revoke | 旧主失去可写数据 | 本地缓存、detach 完成语义 |
| network isolation | 阻断已枚举的路径 | 漏掉网络、job 或控制路径 |
| proxy/backend removal | 正常服务不再路由 | 不是数据库 fence |
Patroni watchdog 是一层额外保护:若 mode 为 required 且不能启用 watchdog,节点拒绝
成为 leader;leader 正常运行时必须持续喂狗,否则 watchdog 在超时后触发 reset。它
不能只存在配置文件里,演练要验证设备、权限、超时和真实 reset。
Pigsty 的 patroni_watchdog_mode 支持 off、automatic、required。本章沙箱为
off,所以正式 run 明确只声称 process fence,不声称硬件 watchdog。
顺序不变量
要求 $t_1 \le t_2$。如果无法观测真实 promotion 瞬间,至少在“接受候选为可服务” 之前完成 fence evidence;不要用事后日志倒推一个未经保护的时间窗不存在。
本章正式结果:
这是一台可控虚拟机上的 graceful systemd stop。主机断电、内核 hang 与存储 stall 需要不同 fence,不能复用这组时延。
双主之后不要急着“选数据多的”
若已经观察到两个 writable primary:
- 阻断外部写,记录每条路由与 writer;
- 保存两边 system identifier、timeline、LSN 与业务 identity;
- 取得至少一边的可信 fence;
- 由业务 authority 选择权威分支;
- 隔离提取另一分支独有的合法事实;
- 用逻辑对账合并,而不是直接让它重新加入;
- 从权威分支 rewind 被舍弃的一侧,或对其做全量重建。
pg_rewind 会舍弃 target 的分叉变化。未先抢救业务事实就 rewind,等于主动销毁可能
需要审计的数据。
33.3.3 自动化不确定时何时转人工
转人工的含义
转人工不是自动执行:
它意味着把状态机停在安全边界,要求人补齐:
三种切换入口
| 入口 | 适用 | leader/candidate | 风险 |
|---|---|---|---|
| automatic failover | 已验证故障与预设策略内 | 由 Patroni/DCS 竞选 | 策略边界内自动 |
| planned switchover | 健康 leader 的维护切换 | 可显式指定 | 可预检、通常低风险 |
| manual failover | leader 不可用且自动路径不能完成 | 必须明确 candidate | 可能放宽 lag/sync 条件并丢数据 |
Patroni REST 文档明确警告 manual failover 可能导致数据损失;无 leader 时,手工候选 可能不受自动 failover 的全部 lag/sync 检查。它是一项风险接受,不是“更强的修复命令”。
Pig 的入口:
--plan 只展示工具计划,不能替代 fence 与 SQL 证据。执行参数以现场 --help 为准;
structured execution 通常还要求显式确认。
自动化停止线
| 不确定性 | 自动动作 |
|---|---|
| old primary writable? unknown | 禁止接受新主 |
| candidate lineage unknown | 禁止 promote |
| DCS split direction unknown | 禁止删 key/重建 DCS |
| manual candidate lag unknown | 禁止 force failover |
| client unknown outcomes unbounded | 可以恢复服务,但不能宣称 RPO |
| backup/archive health unknown | 可以先恢复 HA,必须保持生产 gate pending |
自动化可以并行采集和收敛证据,但不能把超时本身当作安全事实。一个 60 秒 timeout 只能 证明“在观察位置没看到预期状态”,不能证明旧主已经断电。
人工决策记录
没有这份记录的 --force,在复盘时无法区分有意识的风险接受与操作失误。
上一节:复制状态与时间线证据 · 返回本章目录 · 下一节:DCS 故障的安全处理 · 查看全书目录 · 查看索引中心