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 是谁客户端不需要硬编码 IP1.3 架构图核心要点哨兵至少 3 个且奇数个防止脑裂哨兵和 Redis 节点可以部署在同一台机器但建议分开哨兵集群互相通信共同决策二、 哨兵的三个核心任务2.1 监控心跳检测 主观下线哨兵每隔 1 秒向 Master、Slave、其他 Sentinel 发送PING命令。# 哨兵内部执行你不需要手动敲PINGredis_instance如果 PONG 回复正常 → 节点在线如果超过down-after-milliseconds默认 30 秒没收到回复 → 标记为SDOWN主观下线主观下线Subjective DownSDOWN一个哨兵觉得某个节点挂了。2.2 确认客观下线单个哨兵认为 Master 挂了不够因为可能只是网络问题该哨兵自己网络不通。当足够多的哨兵达到 quorum 数量都认为 Master 挂了就会标记为ODOWN客观下线。客观下线条件Sentinel1: “Master 好像挂了” → 投票给 ODOWNSentinel2: “Master 确实挂了” → 投票给 ODOWNSentinel3: “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 当新 MasterLeader Sentinel 从所有 Slave 中筛选筛选条件在线的 Slave排除超过down-after-milliseconds * 10没响应的网络太差排除优先级replica-priority 0的永不被选为 Master打分排序分数越高越优先4.优先级replica-priority值越小越优先默认 1005.复制偏移量offset 越大数据越新越优先6.Run ID如果前面都一样选 Run ID 最小的# 示例Slave1:replica-priority100,offset50000Slave2:replica-priority90,offset48000# 优先级更高当选Slave3:replica-priority100,offset51000# 数据更新当选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哨兵 1Sentinel2127.0.0.126380哨兵 2Sentinel3127.0.0.126381哨兵 33.2 配置 Redis 主从回顾# redis-6379.confMaster 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.confSlave1 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.confSlave2 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 63793.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名字mymasterIP端口quorum2 # 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 同步新 Master1 串行降低压力 sentinel parallel-syncs mymaster 1同样配置sentinel-26380.conf和sentinel-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:namemymaster,statusok,address127.0.0.1:6379,slaves2,sentinels33.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 或 6381redis-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 # 默认 3000030 秒网络不稳定可调大 # 故障转移超时毫秒 sentinel failover-timeout master-name milliseconds # 默认 1800003 分钟超时后认为故障转移失败 # 并行同步数量 sentinel parallel-syncs master-name num # 故障转移后允许几个 Slave 同时同步新 Master # 设置为 1 可避免网络 IO 飙升 # 通知脚本故障转移时执行 sentinel notification-script master-name script-path # 客户端重新配置脚本可选 sentinel client-reconfig-script master-name script-path4.2 哨兵参数调优建议场景down-after-millisecondsfailover-timeoutparallel-syncs内网高速稳定1000010 秒600001 分钟1外网/跨国6000060 秒1800003 分钟1业务要求高可用50005 秒3000030 秒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 → 无响应T030s: 仍无响应 → 标记 SDOWN主观下线T030s: Sentinel1 询问其他 Sentinel“Master 挂了你们觉得呢”Sentinel2: “我也没收到 PONG” → 同意Sentinel3: “我的 PING 正常” → 不同意T030s: 达到 quorum2 → 标记 ODOWN客观下线T030s: 开始故障转移关键点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 rredis.Redis(host192.168.1.100,port6379,passwordxxx)r.set(key,value)# Master 挂了就完了6.2 哨兵方式客户端询问哨兵—— 推荐# ✅ 正确做法fromredis.sentinelimportSentinel# 连接哨兵集群sentinelSentinel([(127.0.0.1,26379),(127.0.0.1,26380),(127.0.0.1,26381)],sentinel_kwargs{password:sentinel_password})# 获取 Master 连接写操作mastersentinel.master_for(mymaster,socket_timeout0.1,passwordmaster_password)# 获取 Slave 连接读操作轮询slavesentinel.slave_for(mymaster,socket_timeout0.1,passwordmaster_password)# 写master.set(name,Redis Sentinel)# 读valueslave.get(name)print(value)JavaJedis示例importredis.clients.jedis.JedisSentinelPool;SetStringsentinelsnewHashSet();sentinels.add(127.0.0.1:26379);sentinels.add(127.0.0.1:26380);sentinels.add(127.0.0.1:26381);JedisSentinelPoolpoolnewJedisSentinelPool(mymaster,sentinels,master_password);try(Jedisjedispool.getResource()){jedis.set(name,Redis Sentinel);Stringvaluejedis.get(name);}pool.close();七、 常见问题与解决方案7.1 脑裂Split-Brain场景网络分区导致哨兵集群分裂选出两个不同的 Master。Redis 的防护哨兵使用多数派决策至少 N/21 个节点同意旧 Master 恢复后发现自己的 epoch 落后自动降级为 Slave虽然不会双写但可能丢数据旧 Master 恢复前的写操作如果没同步到新 Master会永久丢失。解决方案配置min-slaves-to-write# 在 Master 上配置实际需要在每个 Master 候选上配置 min-slaves-to-write 1 min-slaves-max-lag 10 # 如果 Slave 数量 1 或延迟 10sMaster 拒绝写入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 个哨兵仍可选举如果 quorum2# 推荐哨兵独立部署但成本高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.sh8.2 监控告警# 定期检查哨兵状态redis-cli-p26379SENTINEL master mymaster# 输出包括# - num-slaves# - num-other-sentinels# - flagsmaster_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故障转移时怎么选择新 MasterA按优先级筛选优先级最高replica-priority最小复制偏移量最大数据最新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 级数据。哨兵站岗高可用有保障。下期见
Redis基础:6. 哨兵模式
发布时间:2026/6/6 6:35:48
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 是谁客户端不需要硬编码 IP1.3 架构图核心要点哨兵至少 3 个且奇数个防止脑裂哨兵和 Redis 节点可以部署在同一台机器但建议分开哨兵集群互相通信共同决策二、 哨兵的三个核心任务2.1 监控心跳检测 主观下线哨兵每隔 1 秒向 Master、Slave、其他 Sentinel 发送PING命令。# 哨兵内部执行你不需要手动敲PINGredis_instance如果 PONG 回复正常 → 节点在线如果超过down-after-milliseconds默认 30 秒没收到回复 → 标记为SDOWN主观下线主观下线Subjective DownSDOWN一个哨兵觉得某个节点挂了。2.2 确认客观下线单个哨兵认为 Master 挂了不够因为可能只是网络问题该哨兵自己网络不通。当足够多的哨兵达到 quorum 数量都认为 Master 挂了就会标记为ODOWN客观下线。客观下线条件Sentinel1: “Master 好像挂了” → 投票给 ODOWNSentinel2: “Master 确实挂了” → 投票给 ODOWNSentinel3: “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 当新 MasterLeader Sentinel 从所有 Slave 中筛选筛选条件在线的 Slave排除超过down-after-milliseconds * 10没响应的网络太差排除优先级replica-priority 0的永不被选为 Master打分排序分数越高越优先4.优先级replica-priority值越小越优先默认 1005.复制偏移量offset 越大数据越新越优先6.Run ID如果前面都一样选 Run ID 最小的# 示例Slave1:replica-priority100,offset50000Slave2:replica-priority90,offset48000# 优先级更高当选Slave3:replica-priority100,offset51000# 数据更新当选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哨兵 1Sentinel2127.0.0.126380哨兵 2Sentinel3127.0.0.126381哨兵 33.2 配置 Redis 主从回顾# redis-6379.confMaster 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.confSlave1 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.confSlave2 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 63793.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名字mymasterIP端口quorum2 # 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 同步新 Master1 串行降低压力 sentinel parallel-syncs mymaster 1同样配置sentinel-26380.conf和sentinel-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:namemymaster,statusok,address127.0.0.1:6379,slaves2,sentinels33.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 或 6381redis-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 # 默认 3000030 秒网络不稳定可调大 # 故障转移超时毫秒 sentinel failover-timeout master-name milliseconds # 默认 1800003 分钟超时后认为故障转移失败 # 并行同步数量 sentinel parallel-syncs master-name num # 故障转移后允许几个 Slave 同时同步新 Master # 设置为 1 可避免网络 IO 飙升 # 通知脚本故障转移时执行 sentinel notification-script master-name script-path # 客户端重新配置脚本可选 sentinel client-reconfig-script master-name script-path4.2 哨兵参数调优建议场景down-after-millisecondsfailover-timeoutparallel-syncs内网高速稳定1000010 秒600001 分钟1外网/跨国6000060 秒1800003 分钟1业务要求高可用50005 秒3000030 秒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 → 无响应T030s: 仍无响应 → 标记 SDOWN主观下线T030s: Sentinel1 询问其他 Sentinel“Master 挂了你们觉得呢”Sentinel2: “我也没收到 PONG” → 同意Sentinel3: “我的 PING 正常” → 不同意T030s: 达到 quorum2 → 标记 ODOWN客观下线T030s: 开始故障转移关键点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 rredis.Redis(host192.168.1.100,port6379,passwordxxx)r.set(key,value)# Master 挂了就完了6.2 哨兵方式客户端询问哨兵—— 推荐# ✅ 正确做法fromredis.sentinelimportSentinel# 连接哨兵集群sentinelSentinel([(127.0.0.1,26379),(127.0.0.1,26380),(127.0.0.1,26381)],sentinel_kwargs{password:sentinel_password})# 获取 Master 连接写操作mastersentinel.master_for(mymaster,socket_timeout0.1,passwordmaster_password)# 获取 Slave 连接读操作轮询slavesentinel.slave_for(mymaster,socket_timeout0.1,passwordmaster_password)# 写master.set(name,Redis Sentinel)# 读valueslave.get(name)print(value)JavaJedis示例importredis.clients.jedis.JedisSentinelPool;SetStringsentinelsnewHashSet();sentinels.add(127.0.0.1:26379);sentinels.add(127.0.0.1:26380);sentinels.add(127.0.0.1:26381);JedisSentinelPoolpoolnewJedisSentinelPool(mymaster,sentinels,master_password);try(Jedisjedispool.getResource()){jedis.set(name,Redis Sentinel);Stringvaluejedis.get(name);}pool.close();七、 常见问题与解决方案7.1 脑裂Split-Brain场景网络分区导致哨兵集群分裂选出两个不同的 Master。Redis 的防护哨兵使用多数派决策至少 N/21 个节点同意旧 Master 恢复后发现自己的 epoch 落后自动降级为 Slave虽然不会双写但可能丢数据旧 Master 恢复前的写操作如果没同步到新 Master会永久丢失。解决方案配置min-slaves-to-write# 在 Master 上配置实际需要在每个 Master 候选上配置 min-slaves-to-write 1 min-slaves-max-lag 10 # 如果 Slave 数量 1 或延迟 10sMaster 拒绝写入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 个哨兵仍可选举如果 quorum2# 推荐哨兵独立部署但成本高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.sh8.2 监控告警# 定期检查哨兵状态redis-cli-p26379SENTINEL master mymaster# 输出包括# - num-slaves# - num-other-sentinels# - flagsmaster_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故障转移时怎么选择新 MasterA按优先级筛选优先级最高replica-priority最小复制偏移量最大数据最新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 级数据。哨兵站岗高可用有保障。下期见