文章目录
- 每日一句正能量
- 摘要
- 摘要
- 1. 背景与问题
- 1.1 为什么自动切换会产生脑裂
- 1.2 自动故障转移的安全目标
- 2. 环境与数据
- 2.1 脱敏实验拓扑
- 2.2 演练业务数据
- 3. 复现过程
- 3.1 基线验证
- 3.2 场景一:仅切断主备通信
- 3.3 场景二:主库自身网络故障
- 3.4 场景三:仲裁节点不可用
- 3.5 场景四:旧主假死
- 3.6 场景五:网络抖动
- 4. 方案实施
- 4.1 仲裁:用多数派决定写入资格
- 4.2 隔离:先确保旧主不能写
- 4.3 候选备库选择
- 4.4 访问层切换
- 4.5 旧主恢复
- 5. 结果对比
- 5.1 RTO 实测
- 5.2 RPO 实测
- 6. 风险与复盘
- 6.1 仲裁节点自身成为单点
- 6.2 隔离脚本失效
- 6.3 超时设置导致误切换
- 6.4 同步模式与 RPO 的权衡
- 6.5 检查清单
- 总结
每日一句正能量
“当你能将生命的一切经历都视为成长的养分,便终于获得了内在的、不可动摇的从容。”
不筛选、不抗拒,连痛苦、失败、失去都被纳入“养分”的范畴。不依赖外部境遇的好坏来决定内心的稳定。不再与生活对抗,而是与一切遭遇合作。
摘要
本文以生产级高可用集群为背景,讨论自动故障转移中最危险的异常之一——脑裂。文中给出可落地的仲裁、隔离、故障注入、RTO/RPO 实测和检查清单。
摘要
自动故障转移的目标并不是“尽快把备库升为主库”,而是在故障、网络分区和监控误判同时出现时,仍能证明集群中只有一个节点具备写入资格。没有仲裁与隔离的自动切换,本质上只是把人工风险改成自动化风险:切换速度可能更快,但一旦旧主仍在对外写入,就会形成两个主库,各自产生业务流水,后续很难通过普通增量同步无损合并。
本文以一个两数据节点加独立仲裁节点的高可用集群为例,设计主备互联中断、主库外网中断、仲裁节点故障、旧主假死和网络抖动五类故障注入。实施方案遵循三个原则:多数派决定写入资格、提升新主之前先隔离旧主、无法确认安全时宁可停写而不是冒险双写。演练结果通过业务写探针、复制位置、订单流水、摘要校验和时间线记录,分别计算 RTO 与 RPO,并验证故障恢复后旧主只能以备库身份重新加入。
1. 背景与问题
1.1 为什么自动切换会产生脑裂
正常状态下,主库承担写入,备库持续接收并回放日志。守护进程通过数据库连接、心跳和环境检查判断节点是否健康。当主库实例真正停止时,备库提升通常没有争议;困难出现在“看不见对方”而不是“对方已死亡”的场景。
例如,主库与备库之间的复制网络断开,但主库仍能接受应用连接;备库侧守护进程发现主库不可达,误以为主库失效并触发提升。此时:
- 原主库仍在机房 A 接收新订单;
- 新主库在机房 B 接收另一部分订单;
- 两边都认为自己是合法主库;
- 主键、账户余额、库存和流水开始分叉。
这就是脑裂。它不是简单的“复制延迟”,而是产生了两个不可自动合并的写入历史。对订单、支付和账务系统而言,脑裂造成的损失往往高于短时间停机。
1.2 自动故障转移的安全目标
本次方案把安全目标写成可验收的约束,而不是模糊描述:
- 任一时刻,集群中可接受业务写入的数据库节点数量不超过一个。
- 新主提升前,必须确认旧主已经停止服务、失去网络或被 FENCE。
- 无法获得仲裁多数派时,节点不得自行提升。
- 故障恢复后的旧主不得直接以主库身份启动。
- 每次切换必须能计算 RTO、RPO,并留下完整时间线。
2. 环境与数据
2.1 脱敏实验拓扑
| 角色 | 节点 | 位置 | 说明 |
|---|---|---|---|
| 数据库节点 | db-a | 数据中心 A | 初始主库 |
| 数据库节点 | db-b | 数据中心 B | 同步或优选同步备库 |
| 仲裁节点 | arb-c | 独立故障域 C | 只参与投票,不承载业务数据 |
| 访问入口 | db-vip / 代理 | 双中心 | 将写流量指向唯一主库 |
| 监控系统 | monitor | 独立管理区 | 记录心跳、切换与业务恢复时间 |
KingbaseES 高可用集群由主库、备库与守护进程组成,守护进程负责状态检查和故障处理;官方资料还说明网络故障容易造成脑裂,集群可通过信任网关等方式辅助判断本机网络是否异常。正式部署时应以当前版本手册和实际组件能力为准。
2.2 演练业务数据
为了测量 RPO,不能只看数据库进程是否启动,而要持续写入带序号的业务流水。本文使用ha_drill_order表记录:
- 连续订单号;
- 演练批次号;
- 提交时间;
- 实际写入节点;
- 业务载荷摘要。
压测程序每秒写入 100~500 条,发生故障时继续请求,记录成功、失败和重试结果。这样可在切换后检查订单号缺口、重复写入及两个节点是否曾经同时成功写入。
3. 复现过程
3.1 基线验证
演练前先确认:
- 主库可写,备库只读;
- 复制状态正常,回放延迟在阈值内;
- 仲裁节点与两个数据库节点均可达;
- 访问入口只指向当前主库;
- FENCE、远程停库或网络隔离脚本已在维护窗口验证;
- 业务写探针、对账脚本和时间同步均正常。
基线不健康时禁止故障注入。否则演练结果无法区分是方案问题还是既有故障。
3.2 场景一:仅切断主备通信
阻断 db-a 与 db-b 之间的复制和心跳端口,但保留两边到应用网络及仲裁节点的连接。这个场景最能暴露“仅靠节点互相心跳”的风险。
错误实现会出现:db-a 继续写,db-b 因看不到 db-a 而提升,形成双主。正确实现应由仲裁多数派决定哪一侧继续服务,少数派主动停止数据库写入或退出服务入口。
3.3 场景二:主库自身网络故障
隔离 db-a 到信任网关、应用网络和仲裁节点的连接,但 db-a 本机数据库进程仍在运行。此时 db-a 应判断是“本机网络异常”,而不是错误地认为其他节点全部故障。保护动作包括停止对外服务、关闭写入口或执行节点隔离。
3.4 场景三:仲裁节点不可用
停止 arb-c 后再模拟数据库节点间网络异常。由于无法形成可靠多数派,系统应进入保护模式:保持当前已确认主库,或停止自动提升;不能让两个节点分别自选为主。
3.5 场景四:旧主假死
模拟数据库进程无响应、磁盘长时间阻塞或操作系统卡顿,但节点电源仍开、网络时断时续。仅执行“提升备库”是不够的,新主提升前必须确认旧主已被停库、断网、断电或由 FENCE/STONITH 隔离。
3.6 场景五:网络抖动
持续注入延迟、丢包和短时断连。若超时阈值过低,集群会频繁切换;若过高,RTO 又会被拉长。因此应通过多轮实验确定心跳间隔、连续失败次数、切换冷却时间和回切抑制时间。
4. 方案实施
4.1 仲裁:用多数派决定写入资格
两节点集群最大的问题是出现网络分区时双方票数相同。增加独立仲裁节点后,形成奇数票:
- db-a 与 arb-c 可达:db-a 获得多数派;
- db-b 与 arb-c 可达:db-b 获得多数派;
- db-a 与 db-b 可达但仲裁不可达:维持既有主从,不随意提升;
- 单个数据库节点与其他节点均隔离:该节点失去写入资格。
仲裁节点应部署在独立故障域,不能与任一数据库节点共享同一台主机、同一交换机或同一电源故障点。仲裁服务也要监控,否则“有仲裁配置”不等于“仲裁真实可用”。
4.2 隔离:先确保旧主不能写
仲裁解决“谁应该成为主库”,隔离解决“旧主是否真的失去写能力”。常见隔离方式包括:
- 远程停止数据库服务;
- 将旧主从业务 VLAN 或负载均衡中摘除;
- 通过 IPMI、云主机 API 或电源控制执行 FENCE;
- 共享存储场景使用 STONITH 保障资源唯一所有者;
- 撤销旧主的写入 VIP、路由或代理注册。
安全顺序应是:
- 确认故障与仲裁结果;
- 执行旧主隔离;
- 验证旧主写探针失败;
- 选择回放位置最优且健康的备库;
- 提升新主;
- 更新访问入口;
- 验证业务恢复。
任何“先提升、后慢慢隔离”的流程都扩大了双写窗口。
4.3 候选备库选择
多备库环境不能只按节点名称固定提升。应综合判断:
- WAL 接收和回放位置;
- 当前复制状态;
- 复制延迟;
- 数据目录、磁盘和文件系统健康;
- 是否具备多数派;
- 是否能够被应用访问;
- 是否存在长时间恢复或损坏告警。
在同步复制模式下,RPO 可以接近零;异步复制下,仍需根据故障瞬间的发送、接收和回放差距计算实际数据窗口。不能把“自动切换成功”直接等同于“零数据丢失”。
4.4 访问层切换
数据库提升完成不代表业务已经恢复。还需处理:
- VIP 漂移;
- DNS 缓存;
- 数据库代理主节点刷新;
- 连接池失效连接清理;
- 事务重试与幂等控制;
- 只读/读写路由更新。
应用重试必须有上限并具备幂等键,否则切换期间的超时重试可能造成重复订单。业务恢复时间点应以真实接口成功为准,而不是以数据库提升命令返回为准。
4.5 旧主恢复
旧主重新联网后,不允许直接恢复成主库。标准步骤是:
- 保持业务入口隔离;
- 确认时间线和分叉点;
- 判断是否需要重新构建;
- 以备库身份从新主同步;
- 对账通过后加入集群;
- 观察稳定窗口后才恢复读流量。
若脑裂已经发生,应冻结两边写入,按业务流水确定权威数据源并制定专项合并方案,不能直接让两端互相覆盖。
5. 结果对比
本文以三轮脱敏实验展示记录方式,数值仅为示例。
| 方案 | 故障发现 | 旧主隔离 | 新主提升与路由 | 业务 RTO | 实测 RPO | 脑裂结果 |
|---|---|---|---|---|---|---|
| 仅心跳、无仲裁 | 15 秒 | 未完成 | 35 秒 | 50 秒 | 无法可信计算 | 出现双写 |
| 有仲裁、无强隔离 | 15 秒 | 45 秒 | 25 秒 | 85 秒 | 0~2 秒 | 存在短暂风险 |
| 仲裁 + FENCE + 路由门禁 | 12 秒 | 8 秒 | 18 秒 | 38 秒 | 0~1 秒 | 未发生脑裂 |
对比说明一个容易忽略的事实:最短 RTO 不一定是最安全方案。若为了追求几秒切换而省略旧主隔离,可能用极短停机换来不可逆的数据分叉。更合理的目标是先保证写入唯一性,再持续压缩检测、隔离、提升和应用恢复时间。
5.1 RTO 实测
RTO 按下列时间线计算:
- T0:故障注入;
- T1:监控告警;
- T2:旧主隔离完成;
- T3:新主提升完成;
- T4:应用首个关键写接口成功;
- T5:业务对账完成。
严格的业务 RTO 取T4 - T0。若业务要求“对账通过才算恢复”,则采用T5 - T0。报告中必须说明口径,避免只统计数据库提升时间。
5.2 RPO 实测
RPO 至少使用两种方式交叉验证:
- 时间窗口:比较故障前最后确认提交时间与新主最后连续可见时间;
- 流水缺口:检查连续订单号、消息偏移量或业务版本号;
- 摘要对账:比较数量、金额、状态分布和逐批摘要;
- 客户端确认:核对已向客户端返回成功但新主不存在的交易。
只有数据库行数相等并不能证明 RPO 为零,重复提交、状态回退和跨表不一致也必须检查。
6. 风险与复盘
6.1 仲裁节点自身成为单点
仲裁节点不承载业务数据,但其故障会影响自动切换决策。应至少保证:
- 独立故障域;
- 服务自动拉起;
- 容量和磁盘告警;
- 时间同步;
- 多路径网络或清晰的降级策略;
- 定期验证投票状态。
6.2 隔离脚本失效
FENCE 设备、云 API 凭证、IPMI 密码或远程命令可能长期未使用而失效。建议每季度在维护窗口验证一次,并将“隔离成功”作为自动提升的前置条件,而不是仅记录告警后继续切换。
6.3 超时设置导致误切换
超时阈值应依据真实网络 RTT、抖动、磁盘延迟和数据库恢复时间设定。过低会误切换,过高会增加 RTO。建议使用历史监控的 P99 延迟加安全余量,并设置连续失败次数与冷却时间。
6.4 同步模式与 RPO 的权衡
实时同步有助于降低 RPO,但会增加提交路径对网络和备库性能的依赖。异步模式可保持主库写入吞吐,却无法承诺故障时零丢失。应按业务等级分别配置,不应把所有系统套用同一模式。
6.5 检查清单
部署前
- 仲裁节点位于独立故障域;
- 数据库节点、仲裁节点和信任网关地址正确;
- FENCE/停库/断网方式至少一种可验证;
- 主备时间同步和证书、密钥有效;
- 应用连接串、代理和 VIP 具备切换能力;
- 写接口具备幂等键。
演练前
- 复制状态健康,延迟低于门槛;
- 备份与回退方案可用;
- 业务写探针和时间线表已启动;
- 明确暂停条件和人工接管人;
- 记录主备位置、连接数和业务基线。
演练中
- 逐项记录 T0~T5;
- 确认旧主隔离后再提升;
- 验证同一时间仅一个节点写入成功;
- 检查新主读写、序列、任务和权限;
- 监控连接池重连、错误率和重试量。
演练后
- 计算并复核 RTO、RPO;
- 完成数量、金额、状态和流水对账;
- 旧主以备库方式重建;
- 清理临时规则与测试数据;
- 更新阈值、脚本和应急预案;
- 保存日志、截图与个人复盘。
总结
自动故障转移避免脑裂的核心,不是某一条切换命令,而是一条不可绕过的安全链:健康检查发现异常,仲裁确认多数派,隔离剥夺旧主写权限,再提升新主并切换业务入口。其中任何一步缺失,都可能让“高可用”变成“双主高风险”。
真正可信的高可用方案必须通过故障注入证明:主备互联中断、主库网络故障、仲裁失效、旧主假死和网络抖动时,集群仍然最多只有一个写主;还必须用业务流水实测 RTO 与 RPO,而不是只引用产品能力值。高可用演练的目标不是追求一次漂亮的秒级切换,而是形成可重复、可审计、可回退的生产保障流程。
转载自:https://blog.csdn.net/u014727709/article/details/163271002
欢迎 👍点赞✍评论⭐收藏,欢迎指正