🛡️ Redis Sentinel 哨兵
为什么需要 Sentinel?
主从复制解决了读扩展的问题,但如果主节点挂了,需要人工手动切换——半夜被叫醒、手忙脚乱改配置、祈祷没有数据丢失。
**Sentinel(哨兵)**就是来解决这个问题的:它自动监控、自动故障转移、自动通知。你再也不用半夜爬起来手动切换了。
💡 提示: 💡 类比:主从复制是"有一个备份服务器",Sentinel 是"有一个 24 小时值班的运维,主服务器挂了自动切换到备份"。
Sentinel 架构
Sentinel 本身也是一个 Redis 进程,但它不存数据,只负责监控和故障转移。至少需要 3 个 Sentinel 节点(奇数个,用于投票)。
text
┌─────────────┐
│ Sentinel #1 │
└──────┬───────┘
│ 监控
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│Sentinel#2│ │Sentinel#3│ │ │
└──────────┘ └──────────┘ │ 客户端 │
└──────────┘
┌─────────────┐
│ Master │
└──────┬──────┘
│ 复制
┌──────┴──────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Replica1 │ │ Replica2 │
└──────────┘ └──────────┘配置 Sentinel
text
# /etc/redis/sentinel.conf(Sentinel 配置文件)
# 监控主节点(quorum=2 表示至少 2 个 Sentinel 同意才切换)
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点多少秒无响应判定为"主观下线"
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间
sentinel failover-timeout mymaster 30000
# 同时有多少个从节点重新配置指向新主节点
sentinel parallel-syncs mymaster 1
# 主节点密码(如果设置了密码)
sentinel auth-pass mymaster your_password
# 通知脚本(故障转移后执行,如发告警)
sentinel notification-script mymaster /opt/scripts/alert.sh
# 客户端重定向脚本
sentinel client-reconfig-script mymaster /opt/scripts/reconfig.sh启动和查看状态
bash
# 启动 3 个 Sentinel 实例(不同端口)
redis-sentinel /etc/redis/sentinel-26379.conf
redis-sentinel /etc/redis/sentinel-26380.conf
redis-sentinel /etc/redis/sentinel-26381.conf
# 或者用 systemctl
systemctl start redis-sentinel
# 查看 Sentinel 状态
redis-cli -p 26379 sentinel master mymaster
1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "6379"
7) "flags"
8) "master"
# 查看当前从节点
redis-cli -p 26379 sentinel replicas mymaster
# 查看其他 Sentinel 节点
redis-cli -p 26379 sentinel sentinels mymaster
# 模拟故障:停止主节点
redis-cli -p 6379 shutdown
# 观察 Sentinel 日志——自动故障转移
[4290] 20 Jan 10:30:15.123 # +sdown master mymaster 127.0.0.1 6379
[4290] 20 Jan 10:30:20.456 # +odown master mymaster 127.0.0.1 6379
[4290] 20 Jan 10:30:25.789 # +failover-attempt master mymaster 127.0.0.1 6379
[4290] 20 Jan 10:30:26.012 # +failover-end master mymaster 127.0.0.1 6379
[4290] 20 Jan 10:30:26.234 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380客户端连接 Sentinel
python
# Python 客户端连接 Sentinel
from redis.sentinel import Sentinel
# 连接 Sentinel 集群
sentinel = Sentinel([
('127.0.0.1', 26379),
('127.0.0.1', 26380),
('127.0.0.1', 26381),
], socket_timeout=0.5)
# 获取主节点连接(自动发现,自动故障转移)
master = sentinel.master_for('mymaster', socket_timeout=0.5, password='your_password')
master.set('key', 'value')
# 获取从节点连接(读写分离)
replica = sentinel.replica_for('mymaster', socket_timeout=0.5, password='your_password')
value = replica.get('key')
# Java 客户端(Jedis)
// Set<String> sentinels = Set.of("127.0.0.1:26379", "127.0.0.1:26380");
// JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, "password");⚠️ 注意: ⚠️ 客户端必须支持 Sentinel!如果你用的是普通 Redis 客户端(只写死了 IP:Port),故障转移后会连不上新主节点。Python 的redis-py、Java 的Jedis/Lettuce、Node 的ioredis都支持 Sentinel。