Appearance
哨兵模式详解
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 1234564.2 启动 Sentinel
bash
redis-sentinel sentinel.conf
# 或
redis-server sentinel.conf --sentinel4.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 → 成为 Leader5.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 个故障。
