哨兵模式的作用
一句话回答
Redis Sentinel(哨兵)是一个分布式监控系统,负责监控主从状态、自动故障转移(主节点挂了自动选新主)和通知客户端新主节点地址,实现高可用。
哨兵的核心功能
| 功能 | 说明 |
|---|---|
| 监控(Monitoring) | 持续检查主节点和从节点是否正常运行 |
| 通知(Notification) | 通过 API 通知管理员或其他系统节点状态变化 |
| 自动故障转移(Automatic Failover) | 主节点不可用时,选举一个从节点升级为新主 |
| 配置提供(Configuration Provider) | 客户端连接哨兵查询当前主节点地址 |
为什么需要哨兵?
没有哨兵的脆弱性
主机宕机 → 手动切换 → 业务停服 N 分钟
│ │
│ └── 手工执行 SLAVEOF NO ONE
│ 手工修改所有客户端连接地址
▼
业务中断!
有哨兵的高可用
主节点宕机
│
▼
哨兵集群(3+ 个哨兵实例)
│
├── 检测主节点主观下线(S_DOWN)
├── 多个哨兵确认客观下线(O_DOWN) → 开始故障转移
│
├── 选一个从节点升为主 → SLAVEOF NO ONE
├── 其他从节点改为复制新主
│
▼
客户端 → 查询哨兵 → 获取新主地址 → 继续服务
总耗时 ≈ 10-30 秒
配置示例
# sentinel.conf
# 监听主节点(名为 mymaster,IP:port,至少 2 个哨兵同意才认为挂了)
sentinel monitor mymaster 127.0.0.1 6379 2
# 认证密码
sentinel auth-pass mymaster yourpassword
# 主观下线判定时间(30 秒无响应就认为挂了)
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时(3 分钟)
sentinel failover-timeout mymaster 180000
# 同时向新主同步的从节点数(1 = 串行)
sentinel parallel-syncs mymaster 1
启动哨兵
redis-sentinel /etc/redis/sentinel.conf
# 或
redis-server /etc/redis/sentinel.conf --sentinel
故障转移过程详解
时间线:
T+0s 主节点宕机
T+0~30s 哨兵 A 发现主节点无响应 → S_DOWN(主观下线)
T+0~30s 哨兵 B、C 也发现主节点无响应 → S_DOWN
T+30s 至少 2 个哨兵都认为主节点挂了 → O_DOWN(客观下线)
T+30s 选举 leader 哨兵(Raft 算法)
T+30.1s Leader 哨兵执行故障转移:
Step 1: 从从节点中选一个新主
筛选条件:复制偏移最大、配置纪元最新、RUNID 最小
Step 2: 向选中的从节点发送 SLAVEOF NO ONE
Step 3: 等待从节点确认升主完成
Step 4: 向其他从节点发送 SLAVEOF {新主 IP} {新主端口}
Step 5: 修改自身配置,记录新主节点信息
T+32s 故障转移完成
T+32s 客户端重新查询哨兵获取新主地址 → 业务恢复
总耗时:通常 10-30 秒,取决于 down-after-milliseconds 的设置。
哨兵的分布式共识
哨兵至少需要 3 个实例
sentinel monitor mymaster 127.0.0.1 6379 2
# quorum = 2 → 至少 2 个哨兵都认为挂了才算
部署建议:
| 哨兵数量 | 可容忍挂掉数量 | 推荐场景 |
|---|---|---|
| 1 | 0(单点故障) | ❌ 不推荐 |
| 2 | 0(不满足 quorum 时脑裂) | ❌ 不推荐 |
| 3 | 1 | ✅ 最小推荐 |
| 5 | 2 | ✅ 生产环境 |
| 7 | 3 | 超大规格 |
为什么 2 个不够:假设主节点挂了,哨兵 A 认为自己没挂,哨兵 B 认为挂了(网络分区)。quorum=2 需要两个都同意,但网络分区下无法达成一致→不会触发故障转移。
哨兵与客户端交互
客户端发现主节点
import redis
from redis.sentinel import Sentinel
sentinel = Sentinel([('localhost', 26379)],
socket_timeout=0.1)
# 获取当前主节点(自动发现,即使故障转移后)
master = sentinel.master_for('mymaster',
socket_timeout=0.1,
redis_class=redis.StrictRedis)
# 获取从节点(读操作)
slave = sentinel.slave_for('mymaster',
socket_timeout=0.1,
redis_class=redis.StrictRedis)
当发生故障转移时:
客户端 → 查询哨兵(sentinel get-master-addr-by-name mymaster)
→ 获取新主节点 IP:port
→ 自动重建连接
→ 业务无感
面试考点
Q1:哨兵怎么判断主节点真的挂了?
两次判定:
- 主观下线(S_DOWN):单个哨兵发现
down-after-milliseconds时间没收到 PONG - 客观下线(O_DOWN):quorum 个哨兵确认主节点处于 S_DOWN 状态
Q2:哨兵之间怎么通信?
哨兵通过 Redis 的 pub/sub 机制交换信息(__sentinel__:hello 频道),也通过超时和 Raft 协议选举 leader。
Q3:故障转移期间 Redis 能读吗?
- 从节点可以读(但数据不写也不完整,因为主节点宕机)
- 如果
replica-serve-stale-data yes,从节点可读旧数据 - 写操作全都会失败,直到新主节点选举完成
Q4:主节点恢复后怎么处理?
旧主节点恢复后,哨兵会发现它并重新配置为从节点(SLAVEOF 新主)。数据通过全量复制从新主同步。
总结:哨兵模式让 Redis 从「手动运维」升级为「自动高可用」。三个哨兵实例形成最小高可用部署单元,10-30 秒的切换时间适用于绝大多数业务场景。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容