故障转移流程应该怎么设计?
简化版
可靠 Failover 的顺序是确认故障、冻结旧主写权、选择并追平候选、提升新主、切换流量、验证业务与数据,最后进入观察和回补。 最关键的是 fencing 与可验证的状态机;健康检查超时不等于旧主已停止,跳过 fencing 会造成脑裂。
详细版
检测使用多信号和持续窗口,区分实例、网络、依赖与站点故障。控制器通过多数仲裁、租约过期、存储 fencing token 或云 API 隔离旧主,再从日志最完整且满足故障域条件的副本中选新主。复制未追平时要依据 RPO 决定等待还是接受明确的数据缺口。
新主提升后先做小流量读写探测,再修改注册中心、VIP、网关或 DNS。切流期间监控成功率、P99、复制/应用水位、写冲突和容量。所有步骤幂等且有 epoch,重复执行不会二次提升;失败可停在安全状态并按 Runbook 人工接管。
完整版教学
一、Failover 是带安全门槛的状态机
故障转移不是一条“检测到挂了就切”的 if 语句。网络分区时旧主可能仍在运行,只是控制面看不到它;新主若直接接受写,会形成两个权威。流程必须把安全条件写进每次状态迁移。
记忆钩子:先证明旧主不能再写,再让新主开始写;顺序反了就是脑裂窗口。
二、检测要防误判和迟判
HEALTHY -> SUSPECT -> CONFIRMED -> FENCED -> PROMOTING
<- recover --| -> SERVING
单次心跳失败只进入 SUSPECT,多探针、多节点观察或持续 3 个周期后确认。过于敏感会频繁切换,过于迟钝会拉长 RTO。应用错误、节点宕机和控制面网络故障应有不同证据。
三、Fencing 的实现方式
| 方式 | 原理 | 注意点 |
|---|---|---|
| 存储 token/epoch | 只接受更高代际的写入 | 数据层必须强制校验 |
| 租约 | 到期后失去写权 | 需控制时钟与续租 |
| STONITH/云隔离 | 关闭旧节点或网络 | 控制 API 也会失败 |
| 仲裁多数 | 少数派不可提交 | 适用于共识协议 |
仅从负载均衡摘除旧主不能阻止它处理缓存连接、后台任务或直连请求,因此不是完整 fencing。
四、候选选择与 RPO 判断
三副本日志位点 A=1000、B=998、C=990,A 故障后 B 数据最新。若目标 RPO=0 且无法证明 999~1000 未确认,应暂停并人工判断;若业务允许 RPO 5 秒,可提升 B 并记录缺口。候选还需检查故障域、磁盘水位、版本和恢复能力。
提升后生成新 term/epoch,旧请求携带低 epoch 被拒绝。客户端超时重试用业务请求 ID 去重,避免切换窗口重复写。
五、流量切换是多层传播
注册中心、sidecar、VIP、DNS 和客户端连接池的收敛时间不同。优先使用秒级可控的服务发现/VIP,DNS 作为外层入口时不能假设所有递归解析器严格遵循 TTL。先 1% 探测,确认读写与依赖后逐步扩大。
假设检测 15 秒、fencing 10 秒、提升 20 秒、切流 30 秒、验证 15 秒,RTO 至少 90 秒。优化要针对最长阶段,而不是只宣传 20 秒数据库提升。
六、验证、回补和幂等控制
切换成功后核对核心业务成功率、P99、提交与应用水位、积压、数据差异和剩余容量。旧主恢复只能作为只读追赶副本,先回补并校验,不能自动抢回主权。Failback 是独立变更。
控制器每一步写入 durable operationId 与 epoch,重复回调可安全重放。监控状态停留时间、失败原因、人工干预和实际 RPO/RTO,便于演练和复盘。
七、常见误区与追问
- 误区:健康检查失败就证明旧主停止。 网络分区中旧主可能仍处理写入。
- 误区:从 LB 摘流等于 fencing。 直连、后台任务和旧连接仍可能写。
- 误区:选择延迟最低的副本做新主。 应先比较日志完整性和安全资格。
- 误区:故障恢复后自动切回原主最省事。 数据与环境需重新校验,回切应单独执行。
- 追问:控制器自身故障怎么办? 多副本仲裁、幂等状态机,并允许停在安全不可写状态。
- 追问:DNS 切换如何缩短? 合理 TTL、多层流量控制并提前验证解析器行为。
- 追问:如何测真实 RTO? 从业务不可用开始到核心交易通过验证,而非进程启动时间。
八、加强记忆
Failover 按“检测—确认—隔离—选主—提升—切流—验证—回补”记忆。fencing 决定安全,位点决定 RPO,各阶段耗时决定 RTO,epoch 与幂等保证控制动作可重放。切过去只是中点,数据和容量验证通过才算完成。
自动化程度应与证据可靠性匹配:健康信号明确、隔离动作可验证时可自动切;故障原因不明或数据分叉时,应停在安全状态等待人工决策。
因此面试里既要讲“怎么快”,也要讲“什么情况下不能切”,后者更能体现对数据安全边界的理解。