三个顺序状态展示 a 可写、隔离后 a 与 b 均不可写、提升后 b 可写;写者数为 1、0、1,安全过渡允许零写者。

故障切换是一把演练过的开关

备用节点只有在提升路径可用、旧写者不能破坏新历史时才有价值。故障切换既是决策,也是流程与演练。副本看起来健康,不代表客户端能连上它,也不代表所有已确认写入都已经复制过去。先确定恢复时间目标与可接受的数据损失,再决定何时切换,而不是等报警响起才现场讨论。 提前设计好决定 确定谁有权批准提升、什么证据足以说明故障,以及由自动化还是操作员执行。心跳丢失可能是网络分区,而不是主库已经停止。故障检测本身不能授权两个独立写者。系统需要真正执行所有权边界的机制,例如经过确认的节点隔离,或存储端校验的 fencing,并使它与复制协议的保证相匹配。 单写者服务的安全目标是「最多一个被接受的写者」,并非每一瞬间都恰好有一个可用写者。隔离旧节点后、提升新节点前,暂时没有写者可能正是正确的停机选择。操作手册应写明候选节点、复制位置、可接受的丢失范围、客户端如何重连,以及前提不成立时由谁叫停。自动切换能缩短决策时间,却不能凭空补回尚未复制的数据。 演练真实经过的路径 根据风险决定演练频率,并在相关变更后重测。演练只能证明实际覆盖到的路径:绕过 DNS 的数据库提升不能验证地址缓存;测试客户端使用另一套身份,也不能证明生产权限正确。在安全前提下,加入真实的重连流程和已确认写入核对。记录范围、耗时、复制延迟、拒绝条件及恢复证据,不要把最近一次成功的日期当成完整的就绪评分。 开始前先安排安全停止点和恢复步骤。新主库一旦接受写入,切回旧节点往往就不再是撤销一项配置那么简单。旧主库可能需要对账或重建为副本,不能因为进程重新启动就恢复写权限。备份提供另一条恢复路径,但「有备份」本身也不等于已经验证能恢复。 坏掉的样子 旧主库在提升之后仍可写,就会产生脑裂。控制器里记录一句「已隔离」不够,存储或隔离机制必须真正阻止旧写入。落后的候选节点也可能在切换成功后丢失已确认写入。延迟阈值必须有明确单位,并与数据损失目标相连;允许非零延迟,不能同时宣称零数据丢失。 健康检查反复抖动会触发来回切换,应设置明确的故障判定和恢复条件,不要在重新同步之前自动切回。DNS 修改只影响后续查询:已有连接可能持续使用旧地址,按旧 TTL 缓存的回答也不会立刻消失。事故发生时调低 TTL,不能追溯缩短已经缓存的寿命。除了权威 DNS 的响应,还要验证真实客户端的重试、缓存和重连行为,否则控制台显示成功,用户路径仍可能失败。 先隔离,再提升写者。 依据原文与明确限制静态绘制;未为本图重跑原文夹具。 快速验证 使用 Python 3.9 或更新版本,将下面内容保存为 failover_drill.py,在临时目录运行 python3 failover_drill.py。运行时不要使用 -O、-OO 或非零的 PYTHONOPTIMIZE,以免断言被跳过。它只修改内存对象。健康状态和复制延迟是模拟值,fence() 只是更新集合,并不执行真实隔离。模型保留一个被指定的主节点,但隔离期间允许没有可写节点。候选节点通过检查后会被明确解除隔离,因此切回旧节点时不会出现「已经成为主库,却还留在隔离集合中」的自相矛盾状态。 ...

二月 25, 2027 · 3 分钟 · XB Field Notes
五个已知 Sentinel 观察者示意:quorum 二认定故障,多数三授权故障转移。

Sentinel 有两道门:示意。

Redis Sentinel 协调主节点故障转移

Redis Sentinel 监督非 Cluster 的主从部署,并提供当前主节点地址。它不存储应用数据集,也不代理应用命令。主节点失败后自动提升副本,可以帮助恢复写入可用性,但服务发现、副本数据新鲜度、客户端重连以及阻止旧写者继续写入,仍然是不同的问题,不能由“有哨兵”三个字一并保证。 故障认定与选举授权是两道门 一个 Sentinel 在足够长时间收不到可接受回复后,会把实例标记为主观下线;达到配置的 quorum 都认为主节点不可达,才形成客观下线判断。这个故障判定阈值不等于故障转移领导者获得授权所需的多数。选举还必须达到配置的 quorum,因此将 quorum 设置得更高,也可能进一步提高授权门槛。 例如五个已知 Sentinel 配置 quorum 为二,两个观察者可以同意主节点发生故障,但授权提升仍需要三个构成多数。反过来,quorum 为一也不意味着三个已知观察者只剩一个时,它能独自授权。SENTINEL CKQUORUM 会检查这两项可达性条件;某个 Redis 进程看上去健康,并不能证明观察者满足条件。 稳健部署至少需要三个处在独立故障范围内的 Sentinel。同一台笔记本上的三个进程能测试协议行为,却会随整台机器一起失效。每个 Sentinel 还需要可写的配置文件,持久保存发现的拓扑与纪元状态;这些不是随时可以丢弃的普通静态配置,也应保护其中可能存放的认证材料。 提升副本不会阻止所有旧连接写入 Redis 使用异步复制,被选中的副本可能没有收到旧主已经确认的一条写入。网络分区时,留在旧主一侧的客户端甚至可能继续向它写入,而另一侧已经提升替代节点。Sentinel 协调选举,并不等于撤销所有旧连接的写权限,更不会把 Redis 自动变成强一致存储。 min-replicas-to-write、min-replicas-max-lag 等设置可以在复制健康度下降时限制写入,同时牺牲部分可用性;它们不是通用的隔离旧写者协议。仍需独立备份和明确的应用恢复规则。网络分区、复制落后和单纯杀死一个进程应分别验证,不能用其中一个结果替代其他情形。 客户端需要重新发现并建立连接 支持 Sentinel 的客户端先查询观察者拿到主节点地址,再直接连接 Redis。因此,它要处理暂时发现不到主节点、连接断开和角色改变。只认旧地址的客户端,不会因为某个哨兵已经更新答案就自动恢复;同样,写请求超时也不能证明操作从未执行。 下面的代码在发现新的主节点后,明确断开应用的旧连接池,再检查新连接。这样能够单独验证重连环节,而不是承诺故障转移对调用方完全不可见。切换窗口内不能盲目重复非幂等写操作,节点提升并没有替业务提供去重机制。 ...

一月 9, 2027 · 4 分钟 · XB Field Notes