news 2026/6/6 6:35:48

Redis基础:6. 哨兵模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis基础:6. 哨兵模式

Redis 哨兵模式:给 Redis 配上 7x24 小时的值班保安

主从复制只是让 Redis 有了备胎,但备胎转正需要有人来决策——哨兵就是那个发号施令的人

上期我们聊了主从复制,你已经学会了如何让一台 Redis Master 带着一群小弟(Slave)干活。但你有没有想过一个问题:万一 Master 挂了怎么办?

# 凌晨 3 点,Master 突然宕机# 所有写请求全部失败# 你必须手动执行:redis-cli-p6380REPLICAOF NO ONE# 把 Slave 提升为 Master# 然后修改所有应用的配置,指向新的 Master# 整个过程可能需要 10-30 分钟

在互联网时代,10 分钟的不可用 = 巨额损失 + 用户流失。

哨兵(Sentinel)就是为了解决这个问题而生的——它能自动完成故障检测、选举新 Master、通知客户端,整个过程在秒级完成。


一、 哨兵是什么?

1.1 一句话定义

哨兵是 Redis 官方提供的高可用解决方案:它是一个独立运行的进程,负责监控 Redis 主从集群的健康状况,并在 Master 故障时自动完成故障转移(Failover)。

1.2 哨兵能做什么?

功能说明
监控定时检查 Master 和 Slave 是否存活
通知节点宕机时,通过 API 通知系统管理员或其他程序
自动故障转移Master 挂了,自动把某个 Slave 提升为新 Master,其他 Slave 指向新 Master
配置中心客户端连接哨兵,哨兵告诉你当前 Master 是谁(客户端不需要硬编码 IP)

1.3 架构图

核心要点

  • 哨兵至少 3 个(且奇数个),防止"脑裂"
  • 哨兵和 Redis 节点可以部署在同一台机器,但建议分开
  • 哨兵集群互相通信,共同决策

二、 哨兵的三个核心任务

2.1 监控:心跳检测 + 主观下线

哨兵每隔 1 秒向 Master、Slave、其他 Sentinel 发送PING命令。

# 哨兵内部执行(你不需要手动敲)PING<redis_instance>
  • 如果 PONG 回复正常 → 节点在线
  • 如果超过down-after-milliseconds(默认 30 秒)没收到回复 → 标记为SDOWN(主观下线)

主观下线(Subjective Down,SDOWN):一个哨兵觉得某个节点挂了。

2.2 确认:客观下线

单个哨兵认为 Master 挂了不够,因为可能只是网络问题(该哨兵自己网络不通)。

足够多的哨兵(达到 quorum 数量)都认为 Master 挂了,就会标记为ODOWN(客观下线)

客观下线条件
Sentinel1: “Master 好像挂了” → 投票给 ODOWN
Sentinel2: “Master 确实挂了” → 投票给 ODOWN
Sentinel3: “Master 还活着” → 不投票
quorum = 2 → 达到 2 票 → 触发客观下线

2.3 故障转移:选举新 Master

当 Master 被标记为 ODOWN 后,哨兵集群开始选举领导者(Leader Sentinel),由领导者执行故障转移。

2.3.1 领导者选举(Raft 算法变种)
# 每个 Sentinel 都可以发起选举请求# 获得半数以上(并且 >= quorum)投票的 Sentinel 成为 Leader

为什么哨兵需要奇数个:3 个哨兵,最多挂 1 个仍能正常工作;2 个哨兵,挂 1 个就选不出 Leader。

2.3.2 选哪个 Slave 当新 Master?

Leader Sentinel 从所有 Slave 中筛选:

筛选条件

  1. 在线的 Slave
  2. 排除超过down-after-milliseconds * 10没响应的(网络太差)
  3. 排除优先级replica-priority = 0的(永不被选为 Master)

打分排序(分数越高越优先):
4.优先级replica-priority,值越小越优先,默认 100)
5.复制偏移量(offset 越大,数据越新,越优先)
6.Run ID(如果前面都一样,选 Run ID 最小的)

# 示例Slave1:replica-priority=100,offset=50000Slave2:replica-priority=90,offset=48000# 优先级更高,当选Slave3:replica-priority=100,offset=51000# 数据更新,当选
2.3.3 执行故障转移

Leader Sentinel 执行以下操作:

# 1. 把选中的 Slave 提升为 Masterredis-cli-p6380REPLICAOF NO ONE# 2. 让其他 Slave 指向新 Masterredis-cli-p6381REPLICAOF new_master_ip6379# 3. 更新哨兵配置# 4. 通知客户端 Master 已变更

整个过程耗时:通常 10-30 秒。


三、 环境搭建:3 个哨兵 + 1 主 2 从

3.1 架构规划

角色IP端口说明
Master127.0.0.16379主节点
Slave1127.0.0.16380从节点
Slave2127.0.0.16381从节点
Sentinel1127.0.0.126379哨兵 1
Sentinel2127.0.0.126380哨兵 2
Sentinel3127.0.0.126381哨兵 3

3.2 配置 Redis 主从(回顾)

# redis-6379.conf(Master) port 6379 daemonize yes pidfile /var/run/redis-6379.pid logfile /var/log/redis-6379.log dir /var/lib/redis-6379 requirepass master_password masterauth master_password
# redis-6380.conf(Slave1) port 6380 daemonize yes pidfile /var/run/redis-6380.pid logfile /var/log/redis-6380.log dir /var/lib/redis-6380 requirepass master_password masterauth master_password replicaof 127.0.0.1 6379
# redis-6381.conf(Slave2) port 6381 daemonize yes pidfile /var/run/redis-6381.pid logfile /var/log/redis-6381.log dir /var/lib/redis-6381 requirepass master_password masterauth master_password replicaof 127.0.0.1 6379

3.3 配置哨兵

创建sentinel-26379.conf

# 哨兵监听端口 port 26379 daemonize yes pidfile /var/run/sentinel-26379.pid logfile /var/log/sentinel-26379.log dir /var/lib/sentinel-26379 # 监控 Master(名字:mymaster,IP:端口,quorum:2) # quorum = 2 表示至少 2 个哨兵同意,才标记客观下线 sentinel monitor mymaster 127.0.0.1 6379 2 # Master 密码 sentinel auth-pass mymaster master_password # 主观下线时间(毫秒,默认 30 秒) sentinel down-after-milliseconds mymaster 30000 # 故障转移超时(默认 3 分钟) sentinel failover-timeout mymaster 180000 # 同时有多少个 Slave 同步新 Master(1 = 串行,降低压力) sentinel parallel-syncs mymaster 1

同样配置sentinel-26380.confsentinel-26381.conf(只改端口)。

3.4 启动集群

# 1. 启动 Redis 实例redis-server redis-6379.conf redis-server redis-6380.conf redis-server redis-6381.conf# 2. 启动哨兵(两种方式)redis-sentinel sentinel-26379.conf# 或者redis-server sentinel-26379.conf--sentinel# 3. 检查哨兵状态redis-cli-p26379INFO Sentinel

输出示例:

# Sentinelsentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

3.5 测试故障转移

# 1. 模拟 Master 宕机redis-cli-p6379DEBUG SLEEP60# 或者直接 kill# 2. 观察哨兵日志(tail -f /var/log/sentinel-26379.log)# 你会看到类似输出:# +sdown master mymaster 127.0.0.1 6379# +odown master mymaster 127.0.0.1 6379 #quorum 2/2# +new-epoch 1# +try-failover master mymaster 127.0.0.1 6379# +vote-for-leader <哨兵 ID> 1# +elected-leader master mymaster 127.0.0.1 6379# +failover-state-select-slave master mymaster 127.0.0.1 6379# +selected-slave slave 127.0.0.1:6380# +failover-state-send-slaveof-noone slave 127.0.0.1:6380# +failover-state-wait-promotion# +promoted-slave slave 127.0.0.1:6380# +failover-state-reconf-slaves# +slave-reconf-sent slave 127.0.0.1:6381# +slave-reconf-inprog slave 127.0.0.1:6381# +slave-reconf-done slave 127.0.0.1:6381# +failover-end master mymaster 127.0.0.1 6379# 3. 检查新 Master(应该是 6380 或 6381)redis-cli-p6380INFO replication# 你会看到 role:master

四、 核心配置参数详解

4.1 哨兵配置文件

# 监控配置 sentinel monitor <master-name> <ip> <port> <quorum> # quorum:至少多少个哨兵同意,才判定客观下线(不是选举所需的票数) # 密码 sentinel auth-pass <master-name> <password> # 主观下线时间(毫秒) sentinel down-after-milliseconds <master-name> <milliseconds> # 默认 30000(30 秒),网络不稳定可调大 # 故障转移超时(毫秒) sentinel failover-timeout <master-name> <milliseconds> # 默认 180000(3 分钟),超时后认为故障转移失败 # 并行同步数量 sentinel parallel-syncs <master-name> <num> # 故障转移后,允许几个 Slave 同时同步新 Master # 设置为 1 可避免网络 IO 飙升 # 通知脚本(故障转移时执行) sentinel notification-script <master-name> <script-path> # 客户端重新配置脚本(可选) sentinel client-reconfig-script <master-name> <script-path>

4.2 哨兵参数调优建议

场景down-after-millisecondsfailover-timeoutparallel-syncs
内网高速稳定10000(10 秒)60000(1 分钟)1
外网/跨国60000(60 秒)180000(3 分钟)1
业务要求高可用5000(5 秒)30000(30 秒)2

五、 哨兵的工作原理(深入)

5.1 三个定时任务

每个哨兵每秒钟执行以下任务:

任务 1:每 1 秒
向 Master、Slave、其他 Sentinel 发送 PING
任务 2:每 2 秒
通过 Master 的sentinel:hello 频道广播自己的信息
内容:Sentinel IP、端口、Run ID、Master 配置版本号等
任务 3:每 10 秒
向所有 Slave 发送 INFO 命令,获取最新的 Slave 列表

5.2 主观下线 vs 客观下线

时间轴:
T0: Sentinel1 发送 PING → 无响应
T0+30s: 仍无响应 → 标记 SDOWN(主观下线)
T0+30s: Sentinel1 询问其他 Sentinel:“Master 挂了,你们觉得呢?”
Sentinel2: “我也没收到 PONG” → 同意
Sentinel3: “我的 PING 正常” → 不同意
T0+30s: 达到 quorum=2 → 标记 ODOWN(客观下线)
T0+30s: 开始故障转移

关键点

  • SDOWN 是单节点判断
  • ODOWN 是集群共识,才触发故障转移
  • quorum可以设为小于哨兵数量,但不能大于哨兵数量

5.3 配置纪元(Configuration Epoch)

类似于 Raft 的 Term,每次故障转移都会递增。

初始状态:epoch = 0
第一次故障转移:epoch = 1
新的 Master 配置:epoch = 1 的配置
第二次故障转移:epoch = 2
新的 Master 配置:epoch = 2 的配置

作用

  • 哨兵通过 epoch 判断哪个配置是最新的
  • 防止"脑裂":旧 Master 恢复后,发现自己的 epoch 落后,会自动降级为 Slave

六、 客户端连接哨兵

6.1 传统方式(硬编码 Master IP)—— 不推荐

# ❌ 错误做法importredis r=redis.Redis(host='192.168.1.100',port=6379,password='xxx')r.set('key','value')# Master 挂了就完了

6.2 哨兵方式(客户端询问哨兵)—— 推荐

# ✅ 正确做法fromredis.sentinelimportSentinel# 连接哨兵集群sentinel=Sentinel([('127.0.0.1',26379),('127.0.0.1',26380),('127.0.0.1',26381)],sentinel_kwargs={'password':'sentinel_password'})# 获取 Master 连接(写操作)master=sentinel.master_for('mymaster',socket_timeout=0.1,password='master_password')# 获取 Slave 连接(读操作,轮询)slave=sentinel.slave_for('mymaster',socket_timeout=0.1,password='master_password')# 写master.set('name','Redis Sentinel')# 读value=slave.get('name')print(value)

Java(Jedis)示例

importredis.clients.jedis.JedisSentinelPool;Set<String>sentinels=newHashSet<>();sentinels.add("127.0.0.1:26379");sentinels.add("127.0.0.1:26380");sentinels.add("127.0.0.1:26381");JedisSentinelPoolpool=newJedisSentinelPool("mymaster",sentinels,"master_password");try(Jedisjedis=pool.getResource()){jedis.set("name","Redis Sentinel");Stringvalue=jedis.get("name");}pool.close();

七、 常见问题与解决方案

7.1 脑裂(Split-Brain)

场景:网络分区导致哨兵集群分裂,选出两个不同的 Master。

Redis 的防护

  • 哨兵使用多数派决策(至少 N/2+1 个节点同意)
  • 旧 Master 恢复后,发现自己的 epoch 落后,自动降级为 Slave

虽然不会双写,但可能丢数据:旧 Master 恢复前的写操作,如果没同步到新 Master,会永久丢失。

解决方案:配置min-slaves-to-write

# 在 Master 上配置(实际需要在每个 Master 候选上配置) min-slaves-to-write 1 min-slaves-max-lag 10 # 如果 Slave 数量 < 1 或延迟 > 10s,Master 拒绝写入

7.2 哨兵数量为什么是奇数?

哨兵数量最大故障数能否正常工作能否选举
10❌ 挂一个全挂
21❌ 挂一个后剩 1 个,无法达到多数(需要 2 票)
31✅ 挂一个剩 2 个,可选举
41✅ 挂一个剩 3 个,但浪费资源
52✅ 可容忍 2 个故障

结论:3 或 5 个哨兵最经济。永远不要用偶数。

7.3 哨兵和 Redis 部署在一起的风险

# 不推荐:所有哨兵和 Redis 在同一台机器Machine1:Master + Sentinel1Machine2:Slave1 + Sentinel2Machine3:Slave2 + Sentinel3# 问题:Machine1 宕机 → Master + Sentinel1 同时挂# 还剩 2 个哨兵,仍可选举(如果 quorum=2)
# 推荐:哨兵独立部署(但成本高)Machine1:MasterMachine2:Slave1Machine3:Slave2Machine4:Sentinel1Machine5:Sentinel2Machine6:Sentinel3

折中方案:哨兵和 Redis 混部,但保证每个哨兵在不同机器,且quorum = 哨兵数量 / 2 + 1

7.4 故障转移后,旧 Master 恢复怎么办?

旧 Master 重新上线后,发现自己有了新的配置(epoch 更大),会自动降级为 Slave,并同步新 Master 的数据。

# 旧 Master 日志会显示:# MASTER MODE enabled (user request from 'id=...')# 然后收到 SLAVEOF 命令,变为从库


八、 生产环境最佳实践

8.1 推荐配置

# sentinel.conf(所有哨兵统一) # 监控配置 sentinel monitor mymaster 192.168.1.100 6379 2 sentinel auth-pass mymaster your_strong_password # 时间配置(内网高速) sentinel down-after-milliseconds mymaster 10000 # 10 秒 sentinel failover-timeout mymaster 60000 # 1 分钟 # 并行同步数量 sentinel parallel-syncs mymaster 1 # 通知脚本(钉钉/企业微信/邮件) sentinel notification-script mymaster /opt/scripts/alert.sh

8.2 监控告警

# 定期检查哨兵状态redis-cli-p26379SENTINEL master mymaster# 输出包括:# - num-slaves# - num-other-sentinels# - flags(master_down 等)# 关键告警指标# 1. Master 切换次数 > 0 → 可能网络不稳定# 2. num-other-sentinels < 2 → 哨兵掉线# 3. flags 包含 s_down 或 o_down → 立即处理

8.3 备份哨兵配置

# 哨兵的配置是动态更新的(故障转移后自动修改)# 建议定期备份cp/etc/redis/sentinel.conf /backup/sentinel.conf.$(date+%Y%m%d)

九、 哨兵 vs 其他方案

方案自动故障转移数据分片适用场景
主从复制❌ 手动小型应用,可接受手动切换
哨兵中型应用,高可用需求,数据量 < 单机内存
集群✅(内置)大型应用,数据量 > 单机内存

选型建议

  • 数据量 < 16GB,高可用需求 →哨兵
  • 数据量 > 16GB,需要水平扩展 →Redis Cluster(下期讲解)

十、 面试高频题

Q1:哨兵的作用是什么?

A:监控、通知、自动故障转移、配置中心。确保 Redis 集群在主节点故障时能自动恢复。

Q2:哨兵集群至少需要几个?为什么?

A:至少 3 个,并且是奇数。因为哨兵需要选举 Leader 来执行故障转移,需要超过半数的哨兵同意。2 个哨兵挂 1 个后就无法达成多数,3 个哨兵可以容忍挂 1 个。

Q3:主观下线和客观下线的区别?

A:主观下线(SDOWN)是单个哨兵认为 Master 挂了;客观下线(ODOWN)是 quorum 个哨兵都认为 Master 挂了,此时才会触发故障转移。

Q4:故障转移时,怎么选择新 Master?

A:按优先级筛选:

  1. 优先级最高(replica-priority最小)
  2. 复制偏移量最大(数据最新)
  3. Run ID 最小(保底)

Q5:哨兵模式下,客户端怎么连接?

A:客户端连接哨兵集群,询问当前 Master 的 IP 和端口,然后连接 Master。写操作走 Master,读操作可以走 Slave。

Q6:故障转移期间,数据会丢失吗?

A:可能丢失。因为 Redis 主从复制是异步的,Master 宕机时,部分数据可能还没同步到 Slave。可以通过min-slaves-to-write降低丢失概率,但会牺牲可用性。


十一、 总结

哨兵是 Redis 从"单机玩具"走向"生产可用"的关键一步:

阶段可用性运维成本数据容量
单机低(单点故障)受限于内存
主从复制中(手动切换)受限于 Master 内存
哨兵高(自动切换)受限于 Master 内存
集群高 + 水平扩展近乎无限

哨兵模式适合谁

  • 需要高可用,但数据量能放进单机内存(< 32GB)
  • 读多写少,需要读写分离
  • 不想自己实现故障检测和切换

最后的叮嘱

  • 生产环境哨兵数量 = 3 或 5,不要用偶数
  • 不要把所有哨兵和 Redis 放在同一台机器
  • 配置min-slaves-to-write防止脑裂丢数据
  • 客户端必须连接哨兵,不要硬编码 Master IP

下一期预告:Redis Cluster 集群——突破单机内存上限,轻松存储 TB 级数据

哨兵站岗,高可用有保障。下期见!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 6:34:58

2026年主播偷逃税事件的危机公关方案

近年来&#xff0c;随着直播带货行业的迅猛发展&#xff0c;税务合规问题逐渐成为行业关注的焦点。特别是在2026年&#xff0c;多起知名网络主播因偷逃税款被曝光和处罚&#xff0c;不仅对个人声誉造成严重影响&#xff0c;也对整个行业提出了警示。以下是针对此类事件的危机公…

作者头像 李华
网站建设 2026/6/6 6:32:45

深度解析:PyTorch ConvLSTM实现时空序列预测的突破性技术

深度解析&#xff1a;PyTorch ConvLSTM实现时空序列预测的突破性技术 【免费下载链接】ConvLSTM_pytorch Implementation of Convolutional LSTM in PyTorch. 项目地址: https://gitcode.com/gh_mirrors/co/ConvLSTM_pytorch ConvLSTM_pytorch项目为时空序列预测任务提供…

作者头像 李华
网站建设 2026/6/6 6:29:59

从 MySQL 迁移到阿里云 AnalyticDB MySQL:零改造百倍加速实战教程

阿里云 AnalyticDB MySQL 版是 MySQL 用户升级实时数据仓库的首选方案&#xff0c;推荐通过 DTS 实现零停机迁移&#xff0c;实测复杂分析查询性能提升 100 倍以上&#xff0c;完全兼容 MySQL 语法无需改造 SQL&#xff0c;是从 MySQL 迁移到 OLAP 数据仓库的最佳实践。一、为什…

作者头像 李华
网站建设 2026/6/6 6:27:15

【工具】js字符串扩展格式化方法format 格式化文本

有序的格式化文本&#xff0c;使用{number}做为占位符 通常使用&#xff1a;format("this is {0} for {1}", "a", "b") 》 this is a for b 形参: pattern – 文本格式 arguments – 参数 返回值: 格式化后的文本/*** 设置字符串format函数* 例…

作者头像 李华