Skip to content

哨兵模式详解

  Redis Sentinel(哨兵)是 Redis 官方的高可用方案,自动完成故障发现、故障转移、配置通知。有了哨兵,主节点宕机后无需人工干预,秒级自动切换。

一、为什么需要哨兵?

纯主从模式的问题:
  Master 宕机后:
    1. 人工发现(可能几分钟到几小时)
    2. 手动选择一个 Slave 提升为 Master(REPLICAOF NO ONE)
    3. 手动修改其他 Slave 指向新 Master
    4. 手动修改所有客户端连接新 Master
    5. 手动恢复旧 Master 作为 Slave

  ❌ 全人工操作,恢复慢
  ❌ 容易出错

有了哨兵之后:
  Master 宕机后:
    1. Sentinel 自动检测到 Master 下线(秒级)
    2. Sentinels 投票选出 Leader
    3. Leader Sentinel 自动故障转移
    4. 自动通知客户端新 Master 地址

  ✅ 全自动,秒级恢复
  ✅ 无需人工干预

二、Sentinel 架构

┌──────────────────────────────────────────────────────────────────┐
│                      Sentinel 集群                                │
│                                                                  │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐                  │
│  │ Sentinel 1 │  │ Sentinel 2 │  │ Sentinel 3 │  ← 至少 3 个     │
│  │  (Leader)  │  │            │  │            │     (奇数个)     │
│  └──────┬─────┘  └──────┬─────┘  └──────┬─────┘                  │
│         │               │               │                         │
│         └───────────────┼───────────────┘                         │
│                         │ 监控 + 通知                             │
│                         ▼                                         │
│  ┌──────────────────────────────────────────────────────────┐    │
│  │                    Redis 主从集群                          │    │
│  │                                                          │    │
│  │  ┌──────────────┐                                        │    │
│  │  │   Master      │  ← 写操作                              │    │
│  │  └───┬────┬─────┘                                        │    │
│  │      │    │                                               │    │
│  │      ▼    ▼                                               │    │
│  │  ┌──────┐ ┌──────┐                                       │    │
│  │  │Slave1│ │Slave2│  ← 读操作                              │    │
│  │  └──────┘ └──────┘                                       │    │
│  └──────────────────────────────────────────────────────────┘    │
│                                                                  │
│  ★ Sentinel 不存数据,只负责监控和故障转移                         │
│  ★ Sentinel 至少 3 个,保证自身高可用                              │
│  ★ 客户端通过 Sentinel 获取当前 Master 地址                        │
└──────────────────────────────────────────────────────────────────┘

三、Sentinel 核心功能

功能说明
监控定期 PING,检测 Master 和 Slave 是否存活
通知节点故障时通知管理员或其他系统
自动故障转移Master 下线后,自动选举新 Master
配置提供者客户端从 Sentinel 获取当前 Master 地址

四、配置与启动

4.1 sentinel.conf

conf
# 监控 Master
sentinel monitor mymaster 192.168.1.100 6379 2

# 参数说明:
# mymaster         → 集群名称(自定义)
# 192.168.1.100    → Master IP
# 6379             → Master 端口
# 2                → quorum(至少 2 个 Sentinel 认为下线才判定)

# 主观下线超时
sentinel down-after-milliseconds mymaster 30000

# 故障转移超时
sentinel failover-timeout mymaster 180000

# 同时同步的 Slave 数量
sentinel parallel-syncs mymaster 1

# 认证密码
sentinel auth-pass mymaster 123456

4.2 启动 Sentinel

bash
redis-sentinel sentinel.conf
# 或
redis-server sentinel.conf --sentinel

4.3 查看 Sentinel 状态

bash
redis-cli -p 26379
> SENTINEL masters                # 查看所有监控的 Master
> SENTINEL slaves mymaster        # 查看 mymaster 的所有 Slave
> SENTINEL get-master-addr-by-name mymaster  # 获取当前 Master 地址

五、故障转移原理

5.1 主观下线(SDOWN)vs 客观下线(ODOWN)

主观下线(Subjective Down):
  单个 Sentinel 在 down-after-milliseconds 时间内收不到 Master 的 PONG 回复
  → 该 Sentinel 认为 Master 主观下线

客观下线(Objective Down):
  多个 Sentinel 都认为 Master 主观下线
  且数量 ≥ quorum
  → Sentinel 集群判定 Master 客观下线
  → 触发故障转移

  示例:
  quorum = 2
  Sentinel 1: 主观下线 ✅
  Sentinel 2: 主观下线 ✅  → 2 ≥ 2 → 客观下线 → 故障转移
  Sentinel 3: 主观下线 ❌

5.2 Leader Sentinel 选举

故障转移需要选举一个 Leader Sentinel 来执行:

选举规则(Raft 算法简化版):
  1. 每个 Sentinel 都可以向其他 Sentinel 发送投票请求
  2. 每个 Sentinel 在一个纪元(epoch)内只能投一票
  3. 先到先得
  4. 得票数 ≥ (N/2 + 1) 的 Sentinel 成为 Leader
  5. 如果没人过半,等待 2 秒重新选举

  示例(3 个 Sentinel):
  Sentinel 1 向 Sentinel 2 和 3 请求投票
  Sentinel 2 先收到 Sentinel 1 的请求,投票给 1
  Sentinel 3 先收到 Sentinel 1 的请求,投票给 1
  → Sentinel 1 得票 2 + 自己的 1 = 3 ≥ 2 → 成为 Leader

5.3 新 Master 选举

Leader Sentinel 从所有 Slave 中选出新 Master:

筛选条件(必须全部满足):
  ✅ 在线状态(无主观下线)
  ✅ 最近 5 秒内回复过 PING
  ✅ 与旧 Master 的连接断开不超过 down-after-milliseconds × 10

排序规则(优先级从高到低):
  1. slave-priority 最小的优先(配置项,越小越优先)
  2. 复制偏移量最大的优先(数据最新)
  3. runid 最小的优先(字典序,作为最终决胜)

选出新 Master 后:
  1. SLAVEOF NO ONE → 提升为 Master
  2. 其他 Slave → SLAVEOF 新 Master
  3. 旧 Master 恢复后 → SLAVEOF 新 Master(作为 Slave 加入)

5.4 故障转移完整流程

┌────────────────────────────────────────────────────────────────┐
│ 1. 多个 Sentinel 检测到 Master 无响应                          │
│    → 主观下线 (SDOWN)                                          │
│                                                                │
│ 2. Sentinel 之间通信,确认 Master 状态                          │
│    → 达到 quorum → 客观下线 (ODOWN)                             │
│                                                                │
│ 3. 选举 Leader Sentinel                                        │
│    → 得票 ≥ N/2+1                                              │
│                                                                │
│ 4. Leader Sentinel 选举新 Master                               │
│    → 按 slave-priority → offset → runid 排序                   │
│                                                                │
│ 5. 执行故障转移                                                │
│    → 新 Master 执行 SLAVEOF NO ONE                             │
│    → 其他 Slave 执行 SLAVEOF 新 Master                         │
│                                                                │
│ 6. 通知客户端                                                  │
│    → 发布订阅通知:+switch-master                              │
│    → 客户端更新 Master 地址                                    │
│                                                                │
│ 7. 旧 Master 恢复后                                            │
│    → 自动作为 Slave 加入                                       │
└────────────────────────────────────────────────────────────────┘

六、客户端连接 Sentinel

6.1 Jedis 连接

java
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.1.100:26379");
sentinels.add("192.168.1.101:26379");
sentinels.add("192.168.1.102:26379");

JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
Jedis jedis = pool.getResource();  // 自动获取当前 Master 连接

jedis.set("key", "value");
jedis.close();

6.2 Spring Boot 连接

yaml
spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.1.100:26379
        - 192.168.1.101:26379
        - 192.168.1.102:26379

七、面试要点

Q1:Sentinel 的原理是什么?

  Sentinel 集群监控 Redis 主从节点,当 Master 下线时,经过 SDOWN → ODOWN → Leader 选举 → 新 Master 选举,自动完成故障转移。

Q2:Leader Sentinel 是怎么选举的?

  类似 Raft 算法,每个 Sentinel 向其他 Sentinel 请求投票,先到先得,得票 ≥ N/2+1 的成为 Leader。每个纪元只能投一票。

Q3:新 Master 是怎么选出来的?

  先过滤(在线 + 最近回复 + 断开时间不超限),再排序(slave-priority 最小 > offset 最大 > runid 最小)。优先选配置中优先级高、数据最新的 Slave。

Q4:Sentinel 集群至少需要几个?

  至少 3 个(奇数个)。因为 Leader 选举需要多数票(≥ N/2+1),2 个 Sentinel 时,挂一个就选不出 Leader。3 个可以容忍 1 个故障,5 个可以容忍 2 个故障。