2. Redis哨兵模式基础:哨兵架构、故障转移、高可用原理
在微服务架构中,Redis 作为缓存层承担着极高的并发压力。一旦 Redis 主节点宕机,整个微服务链路可能瞬间雪崩。哨兵模式(Sentinel)正是为解决这一问题而设计的分布式高可用解决方案。本章将深入剖析哨兵的核心架构、故障转移机制以及高可用原理,为后续连接池调优打下坚实基础。
2.1 哨兵架构:三节点最小高可用单元
哨兵模式并非单点,而是一个由多个哨兵进程组成的分布式监控系统。一个标准的哨兵架构至少包含以下角色:
| 角色 | 数量 | 职责 |
|---|---|---|
| Redis 主节点 | 1 个 | 处理写入请求,同步数据到从节点 |
| Redis 从节点 | ≥ 1 个 | 复制主节点数据,提供读服务,主节点宕机后参与选举 |
| 哨兵节点 | ≥ 3 个(奇数) | 监控、通知、自动故障转移、配置提供者 |
生产建议:哨兵节点数量必须为奇数(3、5、7),这是为了在故障转移投票时形成多数派(quorum),避免脑裂。2 个哨兵无法达成多数,4 个哨兵与 3 个哨兵的容错能力相同,但增加了网络开销。
下图展示了一个典型的 3 哨兵 + 1 主 2 从的高可用架构:
2.2 哨兵的核心功能:监控、通知、配置、故障转移
哨兵节点在启动后,会持续执行以下四项核心任务:
- 监控(Monitoring):哨兵每隔 1 秒(默认
sentinel monitor间隔)向所有已知的主节点、从节点和其他哨兵发送 PING 命令,检查其可达性。 - 通知(Notification):当被监控的 Redis 实例发生异常时,哨兵通过发布/订阅模式向客户端或其他哨兵发送告警消息。
- 配置提供(Configuration Provider):客户端连接哨兵,询问当前主节点的地址。哨兵返回最新的主节点信息,实现客户端“服务发现”。
- 故障转移(Failover):当主节点被判定为客观下线后,哨兵集群自动选举一个从节点升级为新的主节点,并更新其他从节点的复制目标。
2.3 故障转移流程:从主观下线到新主上任
故障转移是哨兵模式最核心的机制,分为以下 5 个关键步骤:
| 步骤 | 名称 | 详细说明 |
|---|---|---|
| 1 | 主观下线(SDOWN) | 单个哨兵发现主节点在 down-after-milliseconds 时间内未响应 PING,标记该节点为主观下线。 |
| 2 | 客观下线(ODOWN) | 该哨兵通过 SENTINEL is-master-down-by-addr 命令向其他哨兵询问,当收到 ≥ quorum 个确认后,标记为客观下线。 |
| 3 | 选举领导者哨兵 | 哨兵集群使用 Raft 算法选举一个领导者哨兵,由它负责执行故障转移操作。 |
| 4 | 选举新主节点 | 领导者哨兵从健康的从节点中,根据优先级、复制偏移量、运行 ID 等规则选出新主节点。 |
| 5 | 更新拓扑 | 领导者哨兵向新主节点发送 SLAVEOF NO ONE,向其他从节点发送 SLAVEOF new_master,并更新自身配置。 |
关键参数:
quorum:判定客观下线所需的最小哨兵同意数,通常设置为哨兵总数的一半加一(例如 3 个哨兵时 quorum=2)。down-after-milliseconds:哨兵判定节点无响应的时间阈值,默认 30000 毫秒。微服务高并发场景建议适当降低,但需避免网络抖动导致误判。failover-timeout:故障转移超时时间,默认 180 秒。超时后哨兵会放弃本次转移,等待下一次触发。
下图展示了故障转移的完整时序流程:
2.4 高可用原理:Raft 协议与配置纪元
哨兵模式的高可用性建立在两个核心机制之上:
- Raft 领导者选举:当需要执行故障转移时,哨兵集群通过 Raft 协议选举一个领导者。每个哨兵节点拥有投票权,获得超过半数投票的哨兵成为领导者。这保证了在分布式环境下,只有一个哨兵负责执行转移,避免冲突。
- 配置纪元(Configuration Epoch):每次故障转移都会产生一个新的纪元编号(epoch)。哨兵通过纪元来区分新旧配置,防止网络分区恢复后旧主节点重新上线导致的数据混乱。客户端和从节点只信任最新纪元的配置。
微服务场景下的风险提示:
- 脑裂(Split-Brain):当哨兵集群因网络分区无法达成多数时,可能同时存在两个主节点。虽然哨兵通过 quorum 和纪元机制极大降低了概率,但在微服务高并发场景下,仍需在应用层做好幂等和重试保护。
- 故障转移耗时:一次完整的故障转移通常需要 10~30 秒。在此期间,客户端连接池中的旧主节点连接会全部失效,导致大量请求超时。这正是后续章节进行连接池调优的核心原因之一。
2.5 哨兵模式与微服务的适配要点
在微服务架构中,哨兵模式不仅仅是“高可用”,更是“服务发现”的关键组件。以下是几个适配要点:
| 微服务需求 | 哨兵提供的解决方案 | 配置示例 |
|---|---|---|
| 动态获取主节点地址 | 客户端通过哨兵 API 获取当前主节点 IP 和端口 | SENTINEL get-master-addr-by-name mymaster |
| 连接池自动刷新 | 哨兵通过发布/订阅推送主节点变更事件 | SUBSCRIBE +switch-master |
| 读写分离 | 哨兵提供从节点列表,客户端可轮询读取 | SENTINEL slaves mymaster |
| 故障感知与降级 | 哨兵提供 is-master-down-by-addr 接口 |
客户端定期调用,配合断路器模式 |
在微服务中,推荐使用支持哨兵模式的 Redis 客户端(如 Jedis、Lettuce、Redisson),它们内置了哨兵感知和连接池自动刷新能力,能够大幅降低故障转移对业务的影响。
连接池调优前置知识:哨兵模式下的连接池与单机模式有本质区别。客户端需要同时维护到主节点和哨兵节点的连接,并且在故障转移发生时,连接池中的连接会批量失效。理解哨兵的故障转移时序(10~30 秒窗口期),是后续设置连接池超时、最小空闲连接数、测试连接有效性等参数的基础。