Redis 哨兵 (Sentinel)
Redis Sentinel 是 Redis 的高可用解决方案,它提供自动监控、通知、故障转移和配置提供功能。在没有使用 Redis Cluster 的情况下,Sentinel 是实现高可用的最佳选择。
哨兵的核心功能
四大核心能力
- 监控 (Monitoring):持续检查主库和从库是否运行正常,自动发现节点变更
- 通知 (Notification):故障发生时通过 API 通知管理员或系统,支持订阅系统事件
- 自动故障转移 (Automatic Failover):主库故障时,从从库中选举新主库,让其他从库指向新主库
- 配置中心 (Configuration Provider):客户端连接哨兵获取主库地址,发生主从切换时客户端会得到更新
Sentinel 作为分布式系统
Sentinel 本身设计为多个进程协作运行的分布式系统:
- 降低误判:多个 Sentinel 同意某主库不可用时才判定故障
- 系统健壮性:即使部分 Sentinel 故障,系统仍能正常工作
故障判定机制
主观下线 (SDOWN)
单个 Sentinel 节点在 down-after-milliseconds 时间内无法联系到主库,则判定为主观下线。
# Sentinel 配置
sentinel down-after-milliseconds mymaster 30000 # 30 秒无响应判定为主观下线
客观下线 (ODOWN)
当超过 quorum(法定人数)数量的 Sentinel 都认为主库已下线,则判定为客观下线。只有判定为客观下线后,才会触发故障转移。
# quorum = 2 表示需要 2 个 Sentinel 同意才判定为客观下线
sentinel monitor mymaster 127.0.0.1 6379 2
Quorum 与 Majority 的区别
Quorum:判定故障所需的 Sentinel 数量 Majority:授权故障转移所需的 Sentinel 多数票
例如,5 个 Sentinel,quorum = 2:
- 2 个 Sentinel 同意即可判定故障
- 但需要至少 3 个 Sentinel(多数)才能授权故障转移
故障转移流程
完整流程
- 选举领头 Sentinel:Sentinel 集群通过 Raft 类似的算法选出一个 Leader 负责执行故障转移
- 选出新主库:
- 排除下线的从库
- 排除最近断开连接过久的从库
- 优先级:根据
replica-priority(越小越高) - 偏移量:选择复制偏移量最大的(数据最全)
- Run ID:如果以上相同,选择 Run ID 最小的
- 配置转移:让原有从库执行
REPLICAOF新主库 - 旧主归队:当旧主库上线后,Sentinel 会将其降级为新主库的从库
故障转移示例
时间线:
T1: Master 故障,Sentinel 开始检测
T2: 达到 down-after-milliseconds,标记为 SDOWN
T3: quorum 个 Sentinel 同意,标记为 ODOWN
T4: 选举领头 Sentinel
T5: 从从库中选举新 Master
T6: 其他从库复制新 Master
T7: 更新客户端配置
T8: 旧 Master 恢复后成为新 Master 的从库
配置与部署
哨兵配置文件 (sentinel.conf)
# 端口(默认 26379)
port 26379
# 监控主库
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.1.100 6379 2
# 主库密码(如果设置了)
sentinel auth-pass mymaster your_password
# 主观下线判定时间(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 180000
# 同时向新主库发起同步的从库数量
sentinel parallel-syncs mymaster 1
# 工作目录
dir /tmp
配置参数详解
| 参数 | 说明 | 默认值 |
|---|---|---|
down-after-milliseconds | 主观下线判定时间 | 30000ms |
failover-timeout | 故障转移超时时间 | 180000ms |
parallel-syncs | 同时同步的从库数量 | 1 |
quorum | 客观下线判定所需票数 | - |
启动 Sentinel
# 方式一:使用 redis-sentinel 命令
redis-sentinel /path/to/sentinel.conf
# 方式二:使用 redis-server 的 sentinel 模式
redis-server /path/to/sentinel.conf --sentinel
部署建议
最小部署方案
至少需要 3 个 Sentinel 节点,部署在不同的物理服务器或虚拟机上:
+----+
| M1 | Master
| S1 | Sentinel 1
+----+
|
+----+ | +----+
| R2 |----+----| R3 | Replica 2 & 3
| S2 | | S3 | Sentinel 2 & 3
+----+ +----+
Configuration: quorum = 2
部署原则
- 奇数节点:部署奇数个 Sentinel,便于投票决策
- 物理独立:Sentinel 部署在不同的服务器/机架/可用区
- 网络稳定:确保 Sentinel 之间、Sentinel 与 Redis 之间网络稳定
- 客户端支持:确保客户端库支持 Sentinel
Docker/NAT 环境配置
在 Docker 或 NAT 环境中,需要配置 IP 和端口公告:
# 强制 Sentinel 公告特定 IP 和端口
sentinel announce-ip <外部IP>
sentinel announce-port <外部端口>
Sentinel 命令
查询命令
# 连接 Sentinel
redis-cli -p 26379
# 查看主库信息
127.0.0.1:26379> SENTINEL master mymaster
# 查看从库列表
127.0.0.1:26379> SENTINEL replicas mymaster
# 查看其他 Sentinel
127.0.0.1:26379> SENTINEL sentinels mymaster
# 获取当前主库地址
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"
运维命令
# 检查 Sentinel 配置是否正常
127.0.0.1:26379> SENTINEL CKQUORUM mymaster
# 强制重写配置文件
127.0.0.1:26379> SENTINEL FLUSHCONFIG
# 手动触发故障转移
127.0.0.1:26379> SENTINEL FAILOVER mymaster
# 重置主库状态(慎用)
127.0.0.1:26379> SENTINEL RESET mymaster
动态配置
# 运行时修改配置
127.0.0.1:26379> SENTINEL SET mymaster down-after-milliseconds 5000
127.0.0.1:26379> SENTINEL SET mymaster failover-timeout 60000
# 查看全局配置
127.0.0.1:26379> SENTINEL CONFIG GET down-after-milliseconds
# 修改全局配置(Redis 6.2+)
127.0.0.1:26379> SENTINEL CONFIG SET down-after-milliseconds 5000
客户端集成
Java/Spring Boot 集成
在 Spring Boot 中使用 Sentinel 模式:
# application.yml
spring:
redis:
sentinel:
master: mymaster
nodes: 192.168.1.101:26379,192.168.1.102:26379,192.168.1.103:26379
password: your_password
Python 客户端集成
from redis.sentinel import Sentinel
# 配置 Sentinel 节点
sentinel = Sentinel([
('192.168.1.101', 26379),
('192.168.1.102', 26379),
('192.168.1.103', 26379),
], socket_timeout=0.1)
# 获取主库连接
master = sentinel.master_for('mymaster', socket_timeout=0.1)
master.set('key', 'value')
# 获取从库连接(只读)
slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
value = slave.get('key')
Node.js 客户端集成
const Redis = require('ioredis');
const redis = new Redis({
sentinels: [
{ host: '192.168.1.101', port: 26379 },
{ host: '192.168.1.102', port: 26379 },
{ host: '192.168.1.103', port: 26379 },
],
name: 'mymaster',
password: 'your_password',
});
redis.set('key', 'value');
订阅 Sentinel 事件
Sentinel 通过 Pub/Sub 发布事件通知:
# 订阅所有事件
127.0.0.1:26379> SUBSCRIBE +switch-master
127.0.0.1:26379> SUBSCRIBE +failover-end
127.0.0.1:26379> SUBSCRIBE +sdown
127.0.0.1:26379> SUBSCRIBE +odown
常见事件类型:
| 事件 | 说明 |
|---|---|
+switch-master | 主库切换 |
+sdown | 主观下线 |
+odown | 客观下线 |
+failover-end | 故障转移结束 |
+reboot | 实例重启 |
+role-change | 角色变更 |
生产环境最佳实践
1. 部署架构
+--------------------+ +--------------------+ +--------------------+
| Server 1 | | Server 2 | | Server 3 |
| +---------------+ | | +---------------+ | | +---------------+ |
| | Redis Master | | | | Redis Replica | | | | Redis Replica | |
| | Sentinel | | | | Sentinel | | | | Sentinel | |
| +---------------+ | | +---------------+ | | +---------------+ |
+--------------------+ +--------------------+ +--------------------+
2. 配置建议
# 推荐配置
port 26379
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
3. 监控要点
- 监控 Sentinel 进程存活
- 监控主从复制延迟
- 监控 Sentinel 日志中的异常事件
- 定期演练故障转移
4. 常见问题
问题一:故障转移后客户端仍连接旧主库
解决方案:客户端需要实现 Sentinel 支持,自动获取新主库地址。
问题二:网络分区导致脑裂
解决方案:配置 min-replicas-to-write 和 min-replicas-max-lag。
# redis.conf
min-replicas-to-write 1
min-replicas-max-lag 10
问题三:Sentinel 配置不一致
解决方案:使用 SENTINEL FLUSHCONFIG 强制同步配置。
Sentinel vs Redis Cluster
| 特性 | Sentinel | Cluster |
|---|---|---|
| 数据分片 | 不支持 | 支持 |
| 高可用 | 支持 | 支持 |
| 扩展方式 | 只读扩展 | 读写扩展 |
| 配置复杂度 | 低 | 高 |
| 最少节点数 | 3 | 6 |
| 适用场景 | 中小规模、数据量不大 | 大规模、高并发 |
选择建议:
- 数据量小(< 单机内存)、需要高可用 → Sentinel
- 数据量大、需要水平扩展 → Cluster
小结
本章我们学习了:
- Sentinel 核心功能:监控、通知、故障转移、配置中心
- 故障判定机制:主观下线、客观下线、Quorum 和 Majority
- 故障转移流程:选举领头 Sentinel、选举新主库、配置转移
- 配置与部署:配置文件详解、部署架构建议
- 客户端集成:Java、Python、Node.js 客户端配置
- 最佳实践:生产环境部署建议、常见问题解决
练习
- 搭建一个 3 节点的 Sentinel 集群
- 测试故障转移功能:手动停止 Master 观察切换过程
- 使用 Python 客户端连接 Sentinel 并测试自动切换
- 订阅 Sentinel 事件,观察故障转移的事件通知