Redis哨兵模式(Sentinel)详解
一、哨兵模式简介
什么是哨兵模式
哨兵(Sentinel)是一种分布式系统 ,用于监控主从架构中每个节点的运行状态。当主节点(Master)出现故障时,哨兵通过投票机制自动选举新的主节点,并将从节点(Slave)切换到新的主节点,从而实现Redis集群的自动故障转移。
哨兵模式能解决什么问题
在主从复制架构中,如果主节点宕机:
- 从节点无法自动升级为主节点
- 写入操作无法进行
- 服务彻底不可用
哨兵模式就是为了解决这些问题而设计的,它能自动监测、自动转移、自动通知,确保Redis服务的高可用性。
哨兵模式架构图
┌─────────────────┐
│ 哨兵节点 │
│ (Sentinel) │
└────────┬─────────┘
│ PING/PONG (监控)
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────┐ 异步复制 ┌───────────┐ 异步复制 ┌───────────┐
│ 主节点 │───────────►│ 从节点1 │───────────►│ 从节点2 │
│ Master │ │ Slave1 │ │ Slave2 │
└───────────┘ └───────────┘ └───────────┘
架构说明:
- Sentinel → Redis节点:单向发送PING,接收PONG(监控)
- Master → Slave:单向异步复制(数据同步)
- Slave → Master:单向发送ACK确认(复制确认)
二、哨兵模式核心功能
1. 持续监控
哨兵会持续监控主节点和从节点的运行状态,包括:
- 主节点是否可达
- 从节点是否正常复制
- 网络连接是否稳定
2. 自动故障转移
当主节点不可用时,哨兵会自动:
- 检测并确认主节点故障(SDOWN → ODOWN)
- 通过Raft算法选举leader哨兵
- 选择一个从节点升级为新的主节点
- 将其他从节点指向新的主节点
- 通知客户端更新主节点地址
3. 通知机制
故障转移完成后,哨兵支持:
- 通过API通知运维人员
- 发送告警邮件/短信
- 执行自定义脚本(如重启服务、发送通知)
三、故障转移详细流程
1. 主观下线检测
客户端 ──PING──► Redis节点
◄──PONG──
- 哨兵每10秒向Redis节点发送
PING命令 - 如果节点超过
down-after-milliseconds(默认30秒)未响应,哨兵认为该节点主观下线(SDOWN)
2. 客观下线确认
- 多个哨兵节点同时检测到主节点下线
- 达到
quorum配置的数量后,确认客观下线(ODOWN) - 例如:3个哨兵,quorum=2,表示至少2个哨兵认为主节点下线才触发转移
3. 选举Leader哨兵
- 哨兵集群通过Raft算法进行Leader选举
- 只有Leader哨兵才能执行故障转移
- 选举依据:先到先得,优先级高的更容易当选
4. 选择新主节点
Leader哨兵从从节点列表中选择新主节点,选择规则:
- 优先级高的(
replica-priority配置) - 复制偏移量大的(数据最新)
- 运行ID小的(启动时间早)
5. 执行转移
bash
# 原主节点故障后,哨兵执行以下操作:
1. SLAVEOF NO ONE # 让选中的从节点取消从属关系,成为主节点
2. 向其他从节点发送SLAVEOF命令 # 让它们指向新的主节点
3. 更新配置文件 # 记录新的主节点信息
6. 通知客户端
bash
# 哨兵通过发布/订阅机制通知客户端
PUBLISH +switch-master mymaster 192.168.72.11 6379 192.168.72.12 6379
# 格式:新主节点IP 新主节点端口 旧主节点IP 旧主节点端口
四、哨兵配置详解
典型配置文件
conf
# 创建配置目录
mkdir -p /usr/local/redis/sentinel
# 哨兵端口
port 26379
# 守护进程模式
daemonize yes
# PID文件
pidfile /usr/local/redis/redis-sentinel-26379.pid
# 日志文件
logfile "/usr/local/redis/sentinel_26379.log"
# 工作目录
dir /usr/local/redis/sentinel
# 监控主节点配置
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.72.11 6379 2
# 主节点不可达超时时间(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 60000
# 主节点认证密码
sentinel auth-pass mymaster 1234
# 哨兵节点间通信密码(可选)
requirepass "12345"
核心配置项说明
| 配置项 | 说明 | 推荐值 |
|---|---|---|
sentinel monitor |
监控的主节点名称、IP、端口、quorum | quorum=节点数/2+1 |
sentinel down-after-ms |
主观下线超时时间 | 5000ms(5秒) |
sentinel failover-timeout |
故障转移超时时间 | 60000ms(1分钟) |
sentinel auth-pass |
主节点密码 | 与redis.conf一致 |
sentinel parallel-syncs |
同时同步的从节点数量 | 1 |
quorum配置建议
- 3个哨兵节点:quorum设为2
- 5个哨兵节点:quorum设为3
- 原则:quorum > 哨兵节点总数/2
五、常用运维命令
查看集群状态
bash
# 查看哨兵整体信息
redis-cli -p 26379 info sentinel
# 查看监控的主节点列表
redis-cli -p 26379 sentinel masters
# 查看指定主节点详细信息
redis-cli -p 26379 sentinel master mymaster
# 查看从节点信息
redis-cli -p 26379 sentinel slaves mymaster
# 查看所有哨兵节点
redis-cli -p 26379 sentinel sentinels mymaster
# 查询当前主节点地址
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
手动故障转移
bash
# 手动触发故障转移(谨慎使用)
redis-cli -p 26379 sentinel failover mymaster
完整验证示例
bash
# 1. 查看当前主节点
[root@centos ~]# redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "192.168.72.11"
2) "6379"
# 2. 模拟主节点故障
[root@centos ~]# kill <主节点进程ID>
# 3. 查看故障转移日志,可以看到新主节点变为192.168.72.12
# 4. 再次查询主节点地址
[root@centos ~]# redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "192.168.72.12"
2) "6379"
六、客户端如何连接哨兵
工作原理
客户端不直接连接固定的主节点,而是通过哨兵获取主节点地址:
1. 客户端连接哨兵节点列表(预配置)
2. 客户端查询哨兵获取当前主节点地址
3. 客户端直接连接主节点进行读写
4. 哨兵检测到主节点变更,发布通知
5. 客户端刷新主节点地址缓存
6. 下次请求自动路由到新主节点
客户端代码示例(Jedis)
java
// Jedis 2.x/3.x 连接哨兵示例
Set<String> sentinelIPs = new HashSet<>();
sentinelIPs.add("192.168.72.11:26379");
sentinelIPs.add("192.168.72.12:26379");
sentinelIPs.add("192.168.72.13:26379");
// masterName必须与sentinel.conf中的一致,password是Redis密码
JedisSentinelPool pool = new JedisSentinelPool(
"mymaster", // 与sentinel monitor配置的名称一致
sentinelIPs, // 哨兵节点列表
"1234" // Redis密码(与requirepass一致)
);
// 获取连接后即可使用
Jedis jedis = pool.getResource();
jedis.set("key", "value");
String value = jedis.get("key");
// 关闭连接(不是关闭pool)
jedis.close();
关键点:
mymaster必须与哨兵配置中的名称一致- 密码必须与主节点
requirepass一致 JedisSentinelPool内部自动订阅哨兵频道,自动刷新主节点地址
为什么客户端必须通过哨兵
- 主节点地址会动态变化:故障转移后主节点IP/端口会改变,客户端无法预知
- 主从切换对客户端透明:客户端只需连接哨兵,由哨兵提供当前主节点地址
七、哨兵模式优缺点
优点
- 高可用保障:自动检测、自动转移,无需人工干预
- 自动选主:从节点自动升级,无需手动配置
- 写分离支持:主节点处理写,从节点处理读,分担压力
- 地址通知:自动通知客户端主节点变化,无需修改客户端配置
- 告警机制:支持通过API和脚本通知运维人员
缺点
- 维护成本较高:至少需要3个哨兵节点,增加部署复杂度
- 故障转移期间有数据丢失风险:异步复制可能导致部分数据丢失
- 客户端需要支持哨兵:老版本客户端可能不支持
八、与主从复制的区别
| 对比项 | 主从复制 | 哨兵模式 |
|---|---|---|
| 核心功能 | 数据同步 | 高可用 + 数据同步 |
| 故障转移 | 手动 | 自动 |
| 主节点选举 | 手动操作 | 自动选举 |
| 客户端配置 | 固定主节点地址 | 连接哨兵获取地址 |
| 运维复杂度 | 低 | 高 |
| 适用场景 | 数据备份、读写分离 | 高可用集群 |
九、面试常见问题
Q1:哨兵模式是如何发现主节点故障的?
答:哨兵通过发送PING命令监测节点响应,如果超过down-after-milliseconds时间未收到响应,标记为主观下线(SDOWN)。当足够多的哨兵(达到quorum)都认为主节点下线时,确认为客观下线(ODOWN)。
Q2:quorum配置为2时,3个哨兵能否完成故障转移?
答:可以。quorum=2表示至少2个哨兵认为主节点下线即可触发故障转移。但实际执行转移的只有被选中的Leader哨兵。
Q3:为什么哨兵至少需要3个节点?
答:3个哨兵可以通过多数投票避免脑裂(split-brain)问题。如果只有2个哨兵,一个哨兵认为主节点下线,另一个认为在线,可能导致数据不一致。
Q4:故障转移期间数据会丢失吗?
答:有可能。因为主从复制是异步的,主节点故障前接收到的部分写操作可能尚未同步到从节点,这些数据会丢失。这是CAP定理中选择AP(可用性+分区容错)的代价。
Q5:客户端如何知道主节点变更了?
答:客户端订阅哨兵的+switch-master频道,故障转移完成后哨兵会发布新的主节点地址,客户端收到通知后自动更新连接地址。