33.4 DCS 故障的安全处理
Patroni 依赖 DCS 保存 leader lock、动态配置与成员协调状态。某节点无法更新 leader lock, 可能是 DCS 整体故障,也可能是该节点落在网络分区的错误一侧。从单个节点看,两者很难 区分:
安全默认是按最坏分区处理:旧主不能续约 authority,就要在 lease 失效前停止写,避免
另一侧取得 lock 后出现双主。failsafe_mode 是一个有严格条件的例外,不是忽略 DCS。
33.4.1 DCS 不可达、失去多数与延迟
先区分四种现象
| 现象 | 可能原因 | 不能立即做 |
|---|---|---|
| 一个 Patroni 到 DCS 超时 | 节点网络、DNS、凭据、DCS | 宣称 DCS 整体宕机 |
| 所有 Patroni 到 DCS 失败 | DCS 失去 quorum、公共网络 | 直接 bootstrap 新 DCS |
| DCS 请求慢但可成功 | 负载、磁盘、网络、GC | 只调大 TTL 掩盖 |
| DCS 有 quorum,某分区不可见 | 不对称网络 | 在不可见一侧手工提升 |
调查矩阵:
同时记录 UTC、monotonic clock、请求耗时和 DCS revision。只记录一次
endpoint health=true 会漏掉尾延迟和间歇超时;只看平均值又会漏掉超过
retry_timeout/lease deadline 的长尾。
DCS 多数派属于 DCS
etcd 通常部署奇数成员。三成员容忍一成员故障,五成员容忍两成员故障;单成员没有 冗余。PostgreSQL 数据节点数量不会补足 etcd quorum。
Pigsty 生产设计应让 infra/DCS 与 PostgreSQL failure domain 相互审阅:
- DCS 成员跨独立电源、主机或可用区;
- latency 满足 lease 与运维目标;
- client/peer 网络和证书可用;
- 备份 DCS 配置与凭据恢复流程,但不把陈旧快照直接覆盖活集群;
- 监控 leader changes、fsync、peer RTT、容量与 auth failure;
- 演练成员故障和 quorum 丢失,不只测
systemctl status。
本章沙箱只有一个 etcd,不能演示多数派。正式实验因此不停止 DCS,只用 blind decision scenario 验证 runbook。
延迟故障比“down”更隐蔽
DCS 还能响应,但延迟接近 Patroni deadline 时可能出现:
正确动作是保存 latency distribution、Patroni loop 时间和 lease revision,处理控制面
性能根因。盲目增大 ttl 会延长故障检测与服务恢复;盲目减小又会让正常长尾触发抖动。
参数变更必须作为容量与失败注入实验,而不是事故现场的猜测。
33.4.2 先保护当前数据库角色,不盲目重置选举状态
failsafe_mode 的严格语义
Patroni DCS failsafe mode 启用后,incumbent primary 在 DCS leader lock 更新因特定
连接类错误失败时,可以向 /failsafe 中全部已知成员发送 Patroni REST 请求。
只有全部成员确认它仍是当前 primary,它才可以继续作为 primary。
为什么不是多数副本确认?DCS quorum 的网络分区与 PostgreSQL 成员分布可能不同。如果 primary 只联系到某个“数据库多数”,DCS 可写分区里的少数 PostgreSQL 节点仍可能取得 leader lock。要求 ALL known members,才能让任何可能竞选的成员知道 incumbent 仍活着。
因此:
若已知成员之一不可达,incumbent 应 demote;DCS 恢复前不会凭空得到新的 authority。
不要删除你还没理解的 key
危险动作:
leader key 是协调事实,不是“卡住的锁文件”。删除它会触发新的 leader race,却不会 自动停止旧主;如果旧主仍写,删除 key 正好制造双主窗口。
先保护:
- 当前 SQL 角色和客户端写入口;
- leader lock、revision、member 与 failsafe 内容;
- 每个 Patroni 的 REST 角色与可达性;
- DCS member/quorum 与 auth 状态;
- 旧主 fence 能力;
- WAL/archive/backup 现场。
需要禁止写时,围住精确业务入口或数据库 authority,不要用破坏 DCS 历史的方式达到 “看起来没主库”。
六个决策场景
本章 failure-model.json 固定六种:
| 场景 | 默认决策 |
|---|---|
| 所有 Patroni 失去 DCS、彼此 REST 全可达 | 观察 failsafe incumbent,不发起新竞选 |
| 仅 primary 失去 DCS、可达全部成员 | 验证 failsafe handshake,replica 不竞选 |
| primary 失去 DCS 且看不到一名已知成员 | old primary 必须 demote/fence 后才接受候选 |
| 仅 replica 失去 DCS | 排除该 replica,保持当前 primary |
| DCS latency 接近 timeout | 控制面事故,停止人工 promotion,保存时间证据 |
| 代理故障伪装成数据库故障 | 修服务路径,不切数据库 |
正式 run 随机抽到“primary 同时失去 DCS 和一个 replica”。正确答案不是立即 promote, 而是先证明旧主只读/停止或由外部 fence 隔离,再确认幸存侧的 DCS authority 与候选 WAL。本次只做决策演练,没有真实注入分区。
33.4.3 恢复控制面后核对 leader lock 与数据库事实
恢复顺序
不要在第 1 步完成后直接开放流量。DCS 恢复只说明控制面重新可读写,数据库可能已经有 两个分支或有成员保留陈旧角色。
四层互证表
| 层 | 唯一主库应看到 | 异常例子 |
|---|---|---|
| DCS | one valid leader lock | no lock / stale identity |
| Patroni REST | one primary with lock, replicas elsewhere | two primaries / unknown |
| SQL | accepted node recovery=false,followers=true | DCS leader SQL 仍 recovery |
| service | write health only points accepted primary | old backend remains healthy |
如果 DCS 指向 A、SQL 却显示 A 在 recovery、B 可写,不要为了让表格一致而手改 key。 先停止流量,保存两边日志、control data 和 timeline,查明谁何时改变角色。
推荐证据命令
SQL:
在 primary 上另查 pg_stat_replication;在 replica 上查 pg_stat_wal_receiver。所有
输出带采集位置、UTC、monotonic sequence 与 hash。REST/DCS 可能含敏感认证信息,证据
包只保留必要 projection,不导出密码、token 或完整配置。
DCS 恢复完成标准
production_gate=pending 时可以继续修复与验证,但不能把技术恢复自动升级成业务批准。
上一节:自动故障转移的保护条件 · 返回本章目录 · 下一节:旧主重加入与集群重建 · 查看全书目录 · 查看索引中心