# 18. Redis 哨兵模式如何保障高可用性,如何处理故障切换?

# 标准答案

Redis 哨兵(Sentinel)模式是 Redis 提供的高可用性(HA)方案,用于监控 Redis 主从集群的状态,自动完成主节点故障检测、从节点选举以及主从切换,确保 Redis 服务的连续可用性。其核心机制包括:主节点监控(Monitoring)、自动故障转移(Failover)、通知机制(Notification)。故障切换流程由多个 Sentinel 节点投票选出新的主节点,并更新配置,保障服务不中断。

# 1️⃣ Redis 哨兵模式的核心机制

Redis 哨兵模式的目标是在主节点故障时,能自动选举新的主节点,并完成主从切换,同时通知客户端更新主节点信息。它的核心工作包括:

# (1)主节点监控(Monitoring)

  • 每个 Sentinel 进程会定期(默认每秒钟)向所有 Redis 节点(主从)发送 PING 命令,检查其状态。
  • 如果 主节点down-after-milliseconds(默认 30 秒)内连续未响应,Sentinel 认为其主观下线(Subjectively Down, SDOWN)
  • 只有当多个 Sentinel 协商一致 后,才会认定主节点客观下线(Objectively Down, ODOWN),触发故障转移。

# (2)自动故障转移(Failover)

当 Sentinel 确认主节点 ODOWN 后,执行以下步骤进行故障切换:

  1. 选举新的主节点(Leader Election)

    • 多个 Sentinel 通过 Raft 算法进行领导者选举,只有被过半数 Sentinel 认可的 Sentinel 才能执行故障切换。
  2. 从节点晋升为新主节点

    • 被选中的 Sentinel 发送 SLAVEOF NO ONE 命令,使某个从节点成为新的主节点。
    • 该 Sentinel 还会要求其他从节点重新复制新主节点,防止脑裂。
  3. 通知客户端更新主节点地址

    • Sentinel 会向客户端发布 +switch-master 消息,告知新主节点的 IP 和端口,使客户端更新连接信息。
  4. 原主节点恢复后的处理

    • 若旧的主节点重新上线,它会被 Sentinel 重新标记为从节点,加入复制集群。

# (3)通知机制(Notification)

  • Sentinel 通过 Pub/Sub 机制,通知 Redis 服务器和其他服务(如应用层)主从切换情况。
  • 客户端可订阅 Sentinel,获取实时的主从变更信息,以便更新 Redis 连接。

# 2️⃣ Redis 故障切换的详细流程

以下是 Redis 哨兵处理主节点故障的完整步骤:

sequenceDiagram
    participant Client
    participant Sentinel1
    participant Sentinel2
    participant Sentinel3
    participant Master
    participant Slave1
    participant Slave2

    Master->>Sentinel1: PING
    Master->>Sentinel2: PING
    Master->>Sentinel3: PING
    Sentinel1-->>Sentinel2: Master 没有响应
    Sentinel2-->>Sentinel3: Master 没有响应
    Sentinel1->>Sentinel2: 确认 ODOWN 状态
    Sentinel2->>Sentinel3: 确认 ODOWN 状态

    Sentinel1->>Sentinel3: 选举 Leader
    Sentinel2->>Sentinel1: 选举 Leader
    Sentinel1->>Sentinel2: 选举成功,Sentinel1 成为 Leader

    Sentinel1->>Slave1: 发送 SLAVEOF NO ONE
    Slave1->>Sentinel1: 变更为新主节点
    Sentinel1->>Slave2: 发送 SLAVEOF 新主节点
    Slave2->>Sentinel1: 变更为从节点

    Sentinel1->>Client: 发送 +switch-master 事件
    Client->>Sentinel1: 更新 Redis 连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 3️⃣ Redis Sentinel 如何保障数据一致性?

# (1)最少从节点可用机制(min-slaves-to-write)

在主节点进行写操作时,Sentinel 可以配置 min-slaves-to-writemin-slaves-max-lag 选项,以确保至少有一定数量的从节点同步到最新数据

  • 示例配置
    min-slaves-to-write 2
    min-slaves-max-lag 10
    
    1
    2
    这个配置表示:
    • 至少 2 个从节点 需要处于可用状态,主节点才能继续处理写操作。
    • 如果从节点的复制延迟超过 10 秒,它将不计入可用从节点。
    • 这可以防止主节点挂掉时,所有从节点都滞后,导致数据丢失。

# (2)避免脑裂(Split-Brain)

Redis Sentinel 通过以下方式防止脑裂(即同时有两个 Redis 认为自己是主节点):

  1. 多 Sentinel 选举机制:只有获得多数 Sentinel 认可的新主节点才会被客户端接受。
  2. 原主节点恢复后自动降级为从节点,避免两个主节点并存。
  3. 使用 quorum(法定人数)参数,确保至少一半以上 Sentinel 参与决策。

例如:

sentinel monitor mymaster 192.168.1.100 6379 3
1

其中 3 代表至少需要 3 个 Sentinel 认定主节点故障,才会触发故障切换。

# 4️⃣ Sentinel 模式的缺陷与优化方案

# (1)哨兵自身的单点故障

  • Sentinel 本身也是一个分布式系统,如果 Sentinel 数量太少,可能会导致误判或者选举失败。
  • 优化方案
    • 部署至少 3 个 Sentinel,确保投票正常进行。
    • 监控 Sentinel 进程,确保其不被意外杀死。

# (2)主从数据复制延迟

  • 在主节点故障时,某些数据可能尚未复制到从节点,导致切换后数据丢失。
  • 优化方案
    • 结合 WAIT 命令,确保数据写入多个从节点后再返回成功。
    • 采用 min-slaves-to-write 确保数据安全性。

# (3)客户端连接更新问题

  • 哨兵不会主动断开客户端连接,客户端需要手动更新 Redis 连接。
  • 优化方案
    • 使用 Redis 提供的 sentinel get-master-addr-by-name 命令自动发现主节点地址。
    • 采用支持 Sentinel 的 Redis 客户端,如 Jedis、Lettuce。

# 深入追问

🔹 Sentinel 和 Redis Cluster 有何区别?何时选用哪种方案?
🔹 在高并发写入场景下,如何确保故障切换时数据不会丢失?
🔹 Sentinel 选举新主节点时,如果所有从节点都滞后 10 秒,怎么办?
🔹 如何监控 Sentinel 进程,确保其不被异常终止?

# 相关面试题

🔹 Redis Sentinel 如何处理脑裂问题?
🔹 如何配置 Redis Sentinel,确保主节点故障后能快速切换?
🔹 Redis Sentinel 和 ZooKeeper 哪种更适合分布式协调?
🔹 如何在 Sentinel 模式下保证主从数据的强一致性?