一文吃透 Redis 哨兵(Sentinel):从"为什么需要"到自动故障转移全流程(含 Raft 选举)
上一篇文章我们聊了 Redis 主从复制:主节点负责写、从节点负责读,数据多副本。但如果主节点本身挂了呢?从节点上有备份没错,可"把从节点提拔成新主节点"这件事,谁来干、怎么干?总不能每次都靠运维半夜爬起来手动切吧。这就是本文的主角——Redis Sentinel(哨兵)。
一、为什么要有哨兵?
1.1 主从复制遗留的问题
主从复制模式下,从节点有两个作用:一是作为主节点的备份,主节点故障时可以"顶"上来;二是分担读压力。但它同样遗留了几个问题:
| 问题 | 说明 | 谁来解决 |
|---|---|---|
| ① 主备切换复杂,需要完全人工参与 | 主节点故障后,要人工选从节点、手动执行切换、通知应用方改地址……故障恢复时间无法保障 | 哨兵(Sentinel)✅ |
| ② 写压力 / 存储压力无法分担 | 写还是只能进主节点,数据还是只能存在一台机器上,受单机限制 | Redis 集群(Cluster) |
哨兵解决的是第一个问题——高可用问题;第二个问题属于存储分布式,留给集群(这是后续博客的内容)。
1.2 人工恢复有多繁琐?
主从复制模式下,主节点故障后需要运维全程介入,大致五步:
- 运维人员通过监控系统发现主节点故障宕机;
- 从所有节点中选一个从节点,执行
slaveof no one,让它晋升为新主节点; - 让其余从节点执行
slaveof {newMasterIp} {newMasterPort},从新主节点同步数据; - 通知所有应用方更新主节点地址;
- 原主节点恢复后,执行
slaveof把它配成一个从节点。
每一步都要人参与,恢复时间不可控——有人工介入的架构,无法称为高可用。Redis 从 2.8 开始提供 Sentinel,把上面五步全部自动化:自动发现故障、自动协商确认、自动选主切换、自动通知应用,整个过程无人值守。
二、哨兵是怎么起作用的?
2.1 哨兵的整体架构
哨兵是一个独立的分布式架构,由两部分组成:
- 哨兵节点集合:若干个
redis-sentinel进程(建议奇数个,原因见选举部分),只负责监控、投票、选举和执行故障转移,不存储任何数据; - 数据节点集合:原来的 Redis 主从节点,数据仍然由它们存储。
每个哨兵节点会定期监控:所有的 Redis 数据节点 + 其余的哨兵节点(哨兵之间也互相监控)。
2.2 三个核心功能
- 监控:定期检测 Redis 数据节点、其余哨兵节点是否可达;
- 故障转移:主节点故障时,把从节点晋升(promotion)为新主节点,并维护好后续的主从关系;
- 通知:把故障转移的结果(新主节点是谁)实时通知给应用方。
2.3 故障转移的完整流程(重点)
主节点故障后,哨兵按下面四步自动完成切换:
第 1 步:主观下线(SDown)
主节点宕机后,它与哨兵之间的心跳包消失了。站在单个哨兵的角度,它判定"主节点不可达"——这只是它自己的看法,所以叫主观下线。
为什么要区分主观/客观?因为单个哨兵可能误判:比如主节点其实活得好好的,是这个哨兵自己的网络被孤立了,它以为主节点挂了。
第 2 步:客观下线(ODown)
一旦有哨兵认为主节点主观下线,它就会询问其他哨兵:"你们觉得主节点挂了吗?“所有哨兵对这件事投票,当故障得票数 ≥ 法定票数时,主节点故障这件事被"做实”,触发客观下线。
法定票数就是sentinel monitor配置的第 4 个参数:
# sentinel monitor 主节点名 主节点ip 主节点端口 法定票数sentinel monitor redis-master172.22.0.463792用投票来做实故障,正是为了防止"出故障的不是主节点,而是发现故障的哨兵"这种误判场景。
第 3 步:选举哨兵 leader(Raft 算法)
客观下线后,需要有人去执行"提拔从节点"的工作。这件事不需要所有哨兵都参与,只需要选出一名代表——leader,由它负责后续的故障转移。
选举用的是Raft 算法,在哨兵中的玩法是:
- 每个哨兵都向其他所有哨兵发起"拉票请求"(S1→S2、S1→S3、S2→S1……);
- 收到请求的哨兵回复"投票响应":每个哨兵只有一票,如果它还没投给别人,就投给第一个来拉票的,否则拒绝;
- 一轮投票后,得票超过半数的节点自动成为 leader;如果平票(S1 投 S2、S2 投 S3、S3 投 S1),重新再投一次即可;
- leader 负责挑选从节点执行晋升;当其他哨兵发现新的 master 出现了,说明选举结束。
Raft 的核心就一句话:“先下手为强”——谁先发出拉票请求,谁就更大概率当选,而"谁先"取决于网络延时的随机性。具体哪个节点当选不重要,重要的是能选出一个。
这里只介绍 Raft 在哨兵中的用法;Raft 算法本身的详细讲解(任期、日志复制、心跳等),请看我后续的博客《一文吃透 Raft 算法》。
第 4 步:leader 执行故障转移
leader 按三条规则从剩余从节点中挑选新的 master:
按顺序比较,先比出结果就胜出:
- 比较优先级:
replica-priority数值越小的优先级越高,直接上位(这是配置文件里"钦定"的); - 比较复制偏移量(replication offset):谁从主节点复制的数据多、offset 大,谁上位——数据更新的从节点当选,可以减少数据丢失;
- 比较 run id:前两条都比不出来时,run id 小的上位(兜底规则)。
选出来之后,leader 做三件事:
- 让选中的从节点执行
slaveof no one→ 成为新的 master; - 让其余从节点
slaveof这个新 master → 重新建立主从关系; - 把变化通知应用方,让客户端把请求发往新主节点。
2.4 故障转移之后
- 原主节点恢复后,会被哨兵重新纳入监控,但只会作为从节点使用,不会自动夺回主节点身份;
- 哨兵运行中会自动重写(rewrite)自己的配置文件,记录新的主节点信息——所以每个哨兵要单独一份配置文件,避免多个哨兵改同一个文件互相干扰;
down-after-milliseconds参数控制心跳超时判定:心跳包在指定时间内没回来,就视为节点故障。
三、注意事项与总结
- 哨兵节点不能只有一个——否则哨兵自己挂了,同样影响系统可用性;
- 哨兵节点最好是奇数个——方便选举 leader,得票更容易超过半数,减少平票重投的开销;
- 哨兵节点不负责存储数据——存储仍然由 Redis 主从节点负责;
- 哨兵 + 主从复制解决的是"高可用",不能解决"数据极端情况下写丢失"的问题,也不能提升存储容量——数据量超过单机内存时,就需要Redis 集群来分片了;
- 主观下线(SDown)→ 客观下线(ODown)→ Raft 选 leader → leader 执行故障转移,这四步是面试和实战的核心,务必理清;
- Raft 选举的核心是"先下手为强",每个哨兵一票、投给第一个拉票的、超过半数当选。
系列文章导航:Redis 持久化 → 主从复制 →哨兵机制(本文)→ Raft 算法(写作中)→ Redis 集群(规划中)。如果本文对你有帮助,欢迎点赞、收藏、评论交流!