被动故障检测

被动故障检测(节点宕机,网络分区)场景下的 RTO 时序分析

被动故障检测,整个节点/Patroni 停止

Pigsty 提供了四种 RTO 配置策略,下面是对三类故障场景下,不同 RTO 模式的最差,最优,平均 RTO 的计算逻辑与结果分析。

被动检测

节点宕机/网络分区场景(被动检测)RTO 对比

模式 最好 RTO 平均 RTO 最坏 RTO TTL 占比
fast 17s 22s 29s 80%
norm 28s 33s 41s 83%
safe 53s 63s 78s 87%
wide 97s 128s 168s 82%

故障路径

RTO 计算公式

RTO = TTL等待 + 从库检测 + 竞争锁 + promote + HAProxy_UP
    = (ttl - loop_wait ~ ttl) + (0 ~ loop_wait) + 选举 + HAProxy_UP

RTO 构成分析

RTO = TTL等待 + loop_wait + 选举(~1s) + HAProxy_UP
      \_____/   \______/
      主要固定成本  可变成本
  • 固定成本:TTL 等待是最大成本(占 80%~87%),这是被动检测的本质代价
  • 可变成本:从库检测延迟(0 ~ loop_wait)
  • HAProxy 延迟:仅计算 rise × fastinter(UP 检测),DOWN 检测与选举并行,不在关键路径

TTL 等待时间的精确计算

Patroni Leader 每 loop_wait 续约一次,将 TTL 重置为完整值。当节点宕机时:

  续约周期示意图:
  
  ──────────────────────────────────────────────────────────────→ 时间
     │                    │                    │
   续约                  续约                  续约
   TTL=ttl              TTL=ttl              TTL=ttl
     │←── loop_wait ───→│
     
  如果故障发生在 Δt 处(续约后 Δt 时间):
  TTL 剩余 = ttl - Δt
  由于 Δt ∈ [0, loop_wait)
  所以 TTL 等待 ∈ (ttl - loop_wait, ttl]

与主动检测(PG 崩溃)的关键差异

对比项 主动检测(PG 崩溃) 被动检测(节点宕机)
主要控制参数 primary_start_timeout ttl
Patroni 状态 存活,主动处理 失效,无法响应
锁释放方式 主动释放 自然过期
RTO 公式核心 2×loop_wait + primary_start_timeout (ttl-loop_wait~ttl) + loop_wait

fast 模式

参数: ttl=20, loop_wait=5, inter=1s, fastinter=500ms, rise=2, fall=2

最好结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 15s ttl - loop_wait = 20 - 5(故障恰好在续约前)
3 从库检测到 Leader 锁过期 0s 从库恰好在 HA loop 检查点
4 从库竞争 Leader 锁 0.1s DCS 单次写操作
5 执行 pg_ctl promote 0.5s WAL 已同步,promote 快速完成
6 HAProxy 检测新主 UP 1s rise=2 × fastinter=500ms
总计 17s

最坏结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 20s 完整 ttl = 20(故障恰好在刚续约后)
3 从库检测到 Leader 锁过期 5s 从库 HA loop 恰好错过,等待下一轮
4 从库竞争 Leader 锁 0.5s DCS 操作 + 网络延迟
5 执行 pg_ctl promote 1s promote + 少量 WAL 回放
6 HAProxy 检测新主 UP 2s rise=2 × inter=1s(从 DOWN 状态开始)
总计 29s

平均结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 18s ttl - loop_wait/2 = 20 - 2.5
3 从库检测到 Leader 锁过期 2.5s loop_wait/2
4 从库竞争 Leader 锁 0.3s DCS 操作平均延迟
5 执行 pg_ctl promote 0.7s promote 平均时间
6 HAProxy 检测新主 UP 1s rise=2 × fastinter
总计 22s

小结

阶段 操作 最好 平均 最坏
1 节点宕机,停止续约 0s 0s 0s
2 等待 TTL 过期 15s 18s 20s
3 从库检测到 Leader 锁过期 0s 2.5s 5s
4 从库竞争 Leader 锁 0.1s 0.3s 0.5s
5 执行 pg_ctl promote 0.5s 0.7s 1s
6 HAProxy 检测新主 UP 1s 1s 2s
总计 17s 22s 29s

fast 模式下节点宕机场景 RTO 范围为 17s ~ 29s,平均约 22s。TTL=20s 是主要耗时(占 80%),由于 loop_wait=5s 的续约频率,实际 TTL 等待范围被压缩到 15~20s。此配置适合同机房低延迟环境,追求最快的被动故障恢复。


norm 模式

参数: ttl=30, loop_wait=5, inter=2s, fastinter=1s, rise=2, fall=3

最好结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 25s ttl - loop_wait = 30 - 5(故障恰好在续约前)
3 从库检测到 Leader 锁过期 0s 从库恰好在 HA loop 检查点
4 从库竞争 Leader 锁 0.1s DCS 单次写操作
5 执行 pg_ctl promote 0.5s WAL 已同步,promote 快速完成
6 HAProxy 检测新主 UP 2s rise=2 × fastinter=1s
总计 28s

最坏结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 30s 完整 ttl = 30(故障恰好在刚续约后)
3 从库检测到 Leader 锁过期 5s 从库 HA loop 恰好错过,等待下一轮
4 从库竞争 Leader 锁 0.5s DCS 操作 + 网络延迟
5 执行 pg_ctl promote 1s promote + 少量 WAL 回放
6 HAProxy 检测新主 UP 4s rise=2 × inter=2s(从 DOWN 状态开始)
总计 41s

平均结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 28s ttl - loop_wait/2 = 30 - 2.5
3 从库检测到 Leader 锁过期 2.5s loop_wait/2
4 从库竞争 Leader 锁 0.3s DCS 操作平均延迟
5 执行 pg_ctl promote 0.7s promote 平均时间
6 HAProxy 检测新主 UP 2s rise=2 × fastinter=1s
总计 33s

小结

阶段 操作 最好 平均 最坏
1 节点宕机,停止续约 0s 0s 0s
2 等待 TTL 过期 25s 28s 30s
3 从库检测到 Leader 锁过期 0s 2.5s 5s
4 从库竞争 Leader 锁 0.1s 0.3s 0.5s
5 执行 pg_ctl promote 0.5s 0.7s 1s
6 HAProxy 检测新主 UP 2s 2s 4s
总计 28s 33s 41s

norm 模式下节点宕机场景 RTO 范围为 28s ~ 41s,平均约 33s。TTL=30s 是主要耗时因素(占 83%)。这是生产环境的平衡选择,在故障恢复速度和集群稳定性之间取得折中。


safe 模式

参数: ttl=60, loop_wait=10, inter=3s, fastinter=1s, rise=2, fall=3

最好结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 50s ttl - loop_wait = 60 - 10(故障恰好在续约前)
3 从库检测到 Leader 锁过期 0s 从库恰好在 HA loop 检查点
4 从库竞争 Leader 锁 0.2s DCS 单次写操作
5 执行 pg_ctl promote 0.5s WAL 已同步,promote 快速完成
6 HAProxy 检测新主 UP 2s rise=2 × fastinter=1s
总计 53s

最坏结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 60s 完整 ttl = 60(故障恰好在刚续约后)
3 从库检测到 Leader 锁过期 10s 从库 HA loop 恰好错过,等待下一轮
4 从库竞争 Leader 锁 1s DCS 操作 + 网络延迟
5 执行 pg_ctl promote 1s promote + 少量 WAL 回放
6 HAProxy 检测新主 UP 6s rise=2 × inter=3s(从 DOWN 状态开始)
总计 78s

平均结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 55s ttl - loop_wait/2 = 60 - 5
3 从库检测到 Leader 锁过期 5s loop_wait/2
4 从库竞争 Leader 锁 0.5s DCS 操作平均延迟
5 执行 pg_ctl promote 0.7s promote 平均时间
6 HAProxy 检测新主 UP 2s rise=2 × fastinter=1s
总计 63s

小结

阶段 操作 最好 平均 最坏
1 节点宕机,停止续约 0s 0s 0s
2 等待 TTL 过期 50s 55s 60s
3 从库检测到 Leader 锁过期 0s 5s 10s
4 从库竞争 Leader 锁 0.2s 0.5s 1s
5 执行 pg_ctl promote 0.5s 0.7s 1s
6 HAProxy 检测新主 UP 2s 2s 6s
总计 53s 63s 78s

safe 模式下节点宕机场景 RTO 范围为 53s ~ 78s,平均约 63s。TTL=60s 提供了充足的容错窗口(占 87%),能有效避免短暂网络抖动导致的误判。此配置适合对稳定性要求极高、可容忍分钟级中断的场景。


wide 模式

参数: ttl=120, loop_wait=30, inter=5s, fastinter=2s, rise=3, fall=5

最好结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 90s ttl - loop_wait = 120 - 30(故障恰好在续约前)
3 从库检测到 Leader 锁过期 0s 从库恰好在 HA loop 检查点
4 从库竞争 Leader 锁 0.5s DCS 单次写操作(广域网延迟)
5 执行 pg_ctl promote 0.5s WAL 已同步,promote 快速完成
6 HAProxy 检测新主 UP 6s rise=3 × fastinter=2s
总计 97s

最坏结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 120s 完整 ttl = 120(故障恰好在刚续约后)
3 从库检测到 Leader 锁过期 30s 从库 HA loop 恰好错过,等待下一轮
4 从库竞争 Leader 锁 2s DCS 操作 + 广域网延迟
5 执行 pg_ctl promote 1s promote + 少量 WAL 回放
6 HAProxy 检测新主 UP 15s rise=3 × inter=5s(从 DOWN 状态开始)
总计 168s

平均结果

阶段 操作 耗时 说明
1 节点宕机,停止续约 0s Patroni + PG 同时失效
2 等待 TTL 过期 105s ttl - loop_wait/2 = 120 - 15
3 从库检测到 Leader 锁过期 15s loop_wait/2
4 从库竞争 Leader 锁 1s DCS 操作平均延迟
5 执行 pg_ctl promote 0.7s promote 平均时间
6 HAProxy 检测新主 UP 6s rise=3 × fastinter=2s
总计 128s

小结

阶段 操作 最好 平均 最坏
1 节点宕机,停止续约 0s 0s 0s
2 等待 TTL 过期 90s 105s 120s
3 从库检测到 Leader 锁过期 0s 15s 30s
4 从库竞争 Leader 锁 0.5s 1s 2s
5 执行 pg_ctl promote 0.5s 0.7s 1s
6 HAProxy 检测新主 UP 6s 6s 15s
总计 97s 128s 168s

wide 模式下节点宕机场景 RTO 范围为 97s ~ 168s(约 1.6~2.8 分钟),平均约 128s(约 2.1 分钟)。TTL=120s 和 loop_wait=30s 提供极强的容错能力(TTL 占 82%),适合广域网/跨数据中心部署。此配置优先保证不误判,代价是故障切换时间较长。