一、Sentinel 的角色与架构
1.1 Sentinel 是什么
Sentinel 是 Redis 官方提供的高可用解决方案,解决主从复制中主节点故障时的自动切换问题。它本质上是独立运行的 Redis 进程(默认端口 26379),不存业务数据,只负责监控、通知、自动故障转移和配置提供四大职能。
# 以 Sentinel 模式启动
redis-sentinel /etc/redis/sentinel.conf
redis-server /etc/redis/sentinel.conf --sentinel
Sentinel 是"监控哨兵"而非"数据节点"。它的内存占用极小(通常几十 MB),但承担了「主节点故障后谁接管」这个关键决策,因此必须以奇数个节点集群部署,绝不能单点运行。
1.2 三种角色协同
一套 Sentinel 体系由三类进程组成:
| 角色 | 端口 | 职责 | 数量 |
|---|---|---|---|
| Master | 6379 | 提供读写,被保护对象 | 1 |
| Replica | 6379 | 数据冗余,故障转移候选 | 1~N |
| Sentinel | 26379 | 监控、选举、故障转移、服务发现 | ≥3(奇数) |
# 典型拓扑:1 主 2 从 3 哨兵
# 节点 A: Master 10.0.0.1:6379 + Sentinel 26379
# 节点 B: Replica 10.0.0.2:6379 + Sentinel 26379
# 节点 C: Replica 10.0.0.3:6379 + Sentinel 26379
1.3 为什么需要三个哨兵
故障转移的正确性依赖多数派决策。1 个哨兵自身宕机即失明;2 个哨兵可能各执一词无法达成多数。3 个是能容忍 1 个哨兵宕机的最小奇数规模。
部署原则:3 个 Sentinel 应分布在不同物理机/可用区,避免机架断电同时宕机。容忍 1 个哨兵故障 → 至少 3 个;容忍 2 个 → 至少 5 个。
二、quorum 与投票机制
2.1 quorum 的含义
quorum(法定票数)是 Sentinel 判定主节点客观下线所需的最少同意票数:
# 监控主节点 mymaster,quorum 为 2
sentinel monitor mymaster 10.0.0.1 6379 2
quorum 有两层语义:一是至少 quorum 个 Sentinel 认为主节点主观下线,才触发客观下线;二是被推举为 leader 的 Sentinel 需获得至少 max(quorum, N/2+1) 票才能执行故障转移。
redis-cli -p 26379 sentinel master mymaster
# 输出包含 quorum、num-other-sentinel-down 等字段
2.2 leader 选举流程
判定客观下线后,发起一次领导者选举(类似 Raft 选主):
- 每个 Sentinel 随机延迟 0~5 秒后自荐为 leader。
- 每个配置纪元(epoch)只能投一票,先到先得。
- 获得多数派(
N/2+1)投票的 Sentinel 成为 leader。 - leader 负责执行故障转移,其他 Sentinel 跟随结果。
# 观察选举纪元与当前主节点
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
# 成功输出新主 ip 与 port
2.3 quorum 数值的取舍
| 部署规模 | 推荐 quorum | 容忍故障 |
|---|---|---|
| 3 哨兵 | 2 | 1 个哨兵 |
| 5 哨兵 | 3 | 2 个哨兵 |
| 7 哨兵 | 4 | 3 个哨兵 |
# quorum=3(3 哨兵)的后果:2 个哨兵失联即无法触发故障转移
# quorum=1 的后果:单个哨兵网络分区即可误判,可能误触发切换
生产环境 3 哨兵 + quorum=2 最常见。quorum 在「避免单点误判」与「快速响应故障」之间取平衡。
三、主观下线与客观下线
3.1 主观下线 S_DOWN
每个 Sentinel 通过心跳 PING 感知主节点状态。在 down-after-milliseconds(默认 30 秒)内无有效回复,即单方面标记主观下线(S_DOWN):
# 10 秒无响应即判定主观下线
sentinel down-after-milliseconds mymaster 10000
3.2 客观下线 O_DOWN
主观下线只是局部判断,可能因网络分区或哨兵误判产生。当至少 quorum 个 Sentinel 都确认该主节点主观下线时,才标记客观下线(O_DOWN),从而允许启动故障转移。
| 对比项 | 主观下线 S_DOWN | 客观下线 O_DOWN |
|---|---|---|
| 判定主体 | 单个 Sentinel | ≥quorum 个 Sentinel |
| 触发动作 | 记录状态、发通知 | 触发选举与故障转移 |
| 可逆性 | PING 恢复后自动清除 | 由新主替代 |
3.3 判定参数详解
sentinel down-after-milliseconds mymaster 10000 # 无响应多久算主观下线
sentinel failover-timeout mymaster 180000 # 故障转移超时(默认 3 分钟)
sentinel parallel-syncs mymaster 1 # 切换后同时同步的从节点数
跨机房部署时
down-after-milliseconds应适当加大(如 30s),避免瞬时抖动触发无谓切换。故障转移本身有代价——客户端重连、短暂不可用,因此宁慢勿快是生产经验。
四、故障转移流程
4.1 从节点筛选
leader 执行故障转移时,第一步从候选从节点里挑选最优者:
- 剔除断线、主观下线、最近连不上的从节点。
- 剔除
slave-priority为 0 的从节点(0 表示永不提升)。 - 剔除复制偏移量落后的从节点(数据越新越优)。
- 优先选择优先级数值小(高优先级)的从节点。
slave-priority 100 # 数值越小优先级越高
slave-priority 0 # 永不被提升
4.2 从节点选举与提升
# leader 自动执行(无需人工干预)
SLAVEOF NO ONE # 候选从节点断开复制成为新主
CONFIG REWRITE # 持久化配置
# 通知其他从节点指向新主
SLAVEOF <new-master-ip> <new-master-port>
# 观察切换事件
redis-cli -p 26379 sentinel events mymaster
# +switch-master mymaster 10.0.0.1 6379 10.0.0.2 6379
4.3 完整时序
T+0s 主节点宕机
T+10s 每个哨兵判定主观下线(down-after-milliseconds=10s)
T+15s 达到 quorum=2,标记客观下线
T+15s leader 选举,多数票胜出
T+17s SLAVEOF NO ONE 提升候选为新主
T+18s 通知其他从节点复制新主
T+20s 更新配置纪元,客户端获取新主地址
从宕机到新主可用通常需要
down-after-milliseconds + 选举时间 + 提升时间,生产一般 10~30 秒。缩短判定时间可加快切换,但会增加误判风险。
五、客户端重定向
5.1 服务发现
Sentinel 的核心价值之一是配置提供:客户端不硬编码主节点地址,而是连接任意 Sentinel 动态获取当前主节点:
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
# 1) "10.0.0.2"
# 2) "6379"
redis-cli -p 26379 sentinel replicas mymaster # 所有从节点
redis-cli -p 26379 sentinel sentinels mymaster # 所有哨兵
5.2 客户端实现
主流客户端(Lettuce、Jedis、go-redis、redis-py、ioredis)都内置 Sentinel 模式:
// Java 示例(Lettuce / Spring Data Redis)
RedisURI uri = RedisURI.Builder
.sentinel("10.0.0.1", 26379, "mymaster")
.withSentinel("10.0.0.2", 26379)
.withSentinel("10.0.0.3", 26379)
.build();
RedisClient client = RedisClient.create(uri);
| 客户端 | 感知机制 | 重连行为 |
|---|---|---|
| Lettuce | 轮询 sentinel get-master-addr-by-name | 自动切换连接 |
| Jedis | 哨兵连接池,故障时重查 | 需配置重试 |
| go-redis | 每次通过 Sentinel 解析 | 自动刷新主地址 |
| redis-py | Sentinel 对象代理连接 | 自动重定向 |
客户端必须配置多个 Sentinel 地址,否则某个哨兵宕机时客户端失去服务发现能力。连接超时与重试参数应覆盖故障转移窗口。
六、3 节点生产部署
6.1 主从配置
# 主节点 redis.conf
bind 0.0.0.0
port 6379
appendonly yes
min-replicas-to-write 1 # 脑裂防护,见第八章
min-replicas-max-lag 10
# 从节点 redis.conf(10.0.0.2 / 10.0.0.3)
replicaof 10.0.0.1 6379
replica-read-only yes
replica-priority 100
# 验证复制状态
redis-cli -p 6379 info replication
# role:master
# connected_slaves:2
# slave0:ip=10.0.0.2,port=6379,state=online,offset=1234,lag=0
6.2 Sentinel 配置
# 每台机器上的 sentinel.conf
port 26379
sentinel monitor mymaster 10.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster <password>
sentinel announce-ip 10.0.0.x # 本机公网/内网地址
# 启动并验证哨兵互相发现
redis-server /etc/redis/sentinel.conf --sentinel
redis-cli -p 26379 sentinel sentinels mymaster # 应列出另外两个哨兵
主节点配置
requirepass时,Sentinel 必须通过sentinel auth-pass提供密码,否则监控失效。announce-ip在 NAT/云负载均衡环境下必须显式配置。
七、Sentinel 命令与 API
7.1 常用运维命令
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster # 当前主节点
redis-cli -p 26379 sentinel master mymaster # 主节点信息
redis-cli -p 26379 sentinel masters # 所有被监控主节点
redis-cli -p 26379 sentinel failover mymaster # 手动强制切换
redis-cli -p 26379 sentinel set mymaster down-after-milliseconds 5000
7.2 动态调整
| 命令 | 作用 | 是否在线生效 |
|---|---|---|
sentinel failover | 手动触发故障转移 | 是 |
sentinel set | 修改运行配置 | 是 |
sentinel flushconfig | 持久化到配置文件 | 是 |
sentinel monitor/unmonitor | 添加/移除监控 | 是 |
sentinel failover是演练和人为切换主节点的利器:无需真宕主节点即可验证整套切换链路。
八、常见坑与避坑
8.1 脑裂问题
主节点与多数哨兵网络分区时,原主仍对外写服务,同时哨兵将某从节点提升为新主 → 出现两个主节点,数据分叉。缓解手段:
# 主节点要求至少写入 1 个副本才返回成功
min-replicas-to-write 1
min-replicas-max-lag 10
失联副本超过阈值时主节点拒绝写请求,从源头避免脑裂期间写入孤儿数据。
8.2 配置与运维坑
| 坑 | 症状 | 规避 |
|---|---|---|
| monitor 里主节点地址写错 | 哨兵误报 down | 核对 ip/port |
| 客户端只配一个哨兵 | 该哨兵宕机后无法感知 | 配置全部哨兵地址 |
| 主从在同一物理机 | 机架断电全挂 | 跨机架/可用区部署 |
| down-after-milliseconds 太小 | 抖动频繁切换 | 结合网络延迟调大 |
| 从节点允许写入 | 切换后数据不一致 | 保持 replica-read-only yes |
| 不演练 | 真正故障时才发现配置错误 | 定期 failover 演练 |
生产经验:Sentinel 体系每季度至少做一次故障转移演练,检查新主数据完整性、从节点自动指向新主、客户端自动恢复、告警正确触发。
九、监控与运维实践
9.1 关键监控指标
redis-cli -p 26379 info sentinel
# sentinel_masters:1
# sentinel_tilt:0
# sentinel_running_scripts:0
| 指标 | 正常值 | 告警阈值 |
|---|---|---|
sentinel_masters | 与配置一致 | 变化即告警 |
sentinel_tilt | 0 | >0 进入倾斜模式告警 |
| 主节点状态 | ok | s_down / o_down 告警 |
| 复制延迟 lag | <1s | >5s 告警 |
| 从节点在线数 | ≥2 | <2 告警 |
9.2 告警与演练
# Prometheus 告警示例:主节点客观下线 30 秒未恢复
alert: RedisMasterDown
expr: redis_sentinel_master_is_down{master="mymaster"} == 1
for: 30s
labels: {severity: critical}
# 演练 1:手动故障转移
redis-cli -p 26379 sentinel failover mymaster
# 演练 2:拔掉主节点电源,观察切换耗时与数据丢失窗口
# 演练 3:原主恢复后核对数据一致性,应自动降级为从节点
演练必须记录每次切换耗时与数据丢失窗口,据此调优参数。业务上需提前决策「要可用还是要数据」——
min-replicas-to-write会在极端情况牺牲可用性换取数据不丢。
结语
- Sentinel 是 Redis 高可用核心,由监控、通知、自动故障转移、配置提供四部分职能组成,必须奇数个哨兵部署以避免单点。
- quorum 决定客观下线与故障转移授权门槛,3 哨兵 + quorum=2 是最常见生产配置。
- 主观下线是单哨兵判断,客观下线需要多数派共识,两者不可混淆。
- 故障转移包括从节点筛选、选举提升与其余从节点重定向,总耗时约 10~30 秒。
- 客户端通过
sentinel get-master-addr-by-name动态发现主节点,必须配置多个哨兵地址并设置合理重试。 - 脑裂风险可通过
min-replicas-to-write缓解,写入前要求至少一个副本在线。 - 生产部署遵循「1 主 2 从 3 哨兵」跨机架/可用区拓扑,并定期进行故障转移演练。
- 监控聚焦哨兵状态、复制延迟、下线标志与从节点在线数,结合 Prometheus 与告警规则闭环。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。