3. 故障转移触发条件:主节点宕机、网络分区、哨兵选举过程
在 Redis 高可用架构中,故障转移并非由单一事件触发,而是由哨兵系统通过多阶段检测、确认与协商后自动发起。理解触发条件是设计异步导出任务数据源切换策略的前提。本章从主节点宕机、网络分区、哨兵选举三个核心场景展开分析。
3.1 主节点宕机
主节点宕机是最直观的故障场景,通常由硬件故障、OOM、内核崩溃或 Redis 进程异常退出引起。哨兵通过以下流程检测并确认主节点不可用:
| 阶段 | 检测方式 | 超时阈值(默认) | 状态变化 |
|---|---|---|---|
| 主观下线 | 哨兵向主节点发送 PING,未收到 PONG 回复 | down-after-milliseconds(30s) |
标记为 +sdown |
| 客观下线 | 哨兵通过 SENTINEL is-master-down-by-addr 向其他哨兵询问 |
需达到 quorum 数量(默认 2) |
标记为 +odown |
| 发起选举 | 客观下线确认后,哨兵发起 Raft 领导者选举 | 选举超时(2 倍 down-after-milliseconds) |
进入故障转移阶段 |
导出任务影响: 主节点宕机后,所有写入操作立即失败。如果异步导出任务正在读取主节点数据,会触发连接异常。此时导出任务应进入重试等待状态,避免频繁重连加重哨兵负载。
3.2 网络分区
网络分区(Network Partition)比宕机更隐蔽。主节点进程仍在运行,但哨兵或客户端无法与其通信。分区场景分为两类:
- 哨兵与主节点分区: 哨兵无法检测主节点心跳,触发主观下线。若分区持续超过阈值,其他哨兵可能达成客观下线并选举新主节点。
- 客户端与主节点分区: 导出任务所在节点与 Redis 主节点网络中断,但哨兵与主节点通信正常。此时主节点不会发生故障转移,但导出任务无法读取数据。
| 分区类型 | 哨兵行为 | 导出任务行为 | 切换策略 |
|---|---|---|---|
| 哨兵-主节点分区 | 触发客观下线,发起选举 | 连接中断,抛出 READONLY 或超时 |
等待哨兵完成选举后切换至新主节点 |
| 客户端-主节点分区 | 无感知,主节点仍为 +master |
连接超时,无法读取数据 | 本地缓存连接状态,定期重试;若超时过长则主动查询哨兵获取最新主节点 |
| 哨兵集群内部分区 | 多数派哨兵无法协商,选举延迟 | 主节点可能短暂不可用 | 导出任务使用指数退避重试,避免雪崩 |
避坑提示: 网络分区恢复后,旧主节点可能以从节点身份重新加入集群。如果导出任务在分区期间未及时切换数据源,恢复后可能继续向旧主节点写入或读取,导致数据不一致。务必在每次连接前通过哨兵确认当前主节点身份。
3.3 哨兵选举过程
哨兵选举是故障转移的核心决策环节,基于 Raft 共识算法实现。选举过程分为以下步骤:
- 发起选举: 检测到客观下线的哨兵将自己的
current_epoch加 1,并向其他哨兵发送投票请求。 - 投票规则: 每个哨兵在每个 epoch 内只能投一票,优先投票给
runid较小或最先请求的哨兵。 - 选举成功: 获得超过半数哨兵投票的哨兵成为领导者,负责执行故障转移。
- 故障转移执行: 领导者从从节点列表中选出新主节点(优先级最高、复制偏移量最大、runid 最小),并向其他从节点发送
SLAVEOF命令切换复制关系。
3.4 三种触发条件的对比与导出任务应对
| 触发条件 | 检测延迟 | 主节点状态 | 导出任务风险 | 推荐应对策略 |
|---|---|---|---|---|
| 主节点宕机 | 秒级(依赖 PING 超时) | 进程终止 | 连接立即断开,数据读取中断 | 捕获连接异常,进入重试队列;查询哨兵获取新主节点 |
| 网络分区 | 分钟级(依赖分区恢复时间) | 进程存活但不可达 | 连接超时,可能误判主节点状态 | 设置合理的连接超时(建议 5-10s);超时后主动向哨兵发起 SENTINEL get-master-addr-by-name |
| 哨兵选举 | 秒级至分钟级(依赖选举速度) | 可能短暂不可用 | 选举期间主节点地址可能变化 | 选举期间暂停导出任务;选举完成后重新获取主节点地址 |
设计建议: 在异步导出任务中,建议将哨兵地址列表配置为可动态刷新,并在每次执行导出前通过哨兵确认当前主节点。避免在任务启动时一次性获取主节点地址后长期缓存,否则故障转移后导出任务会持续向旧主节点发送请求。