写在前面主从复制解决了数据冗余和读写分离的问题但主节点故障时需要人工干预切换这在生产环境中是不可接受的。Redis哨兵Sentinel机制实现了主节点的自动故障转移是Redis高可用的核心组件。今天我们深入理解哨兵机制的原理与实践。文章目录写在前面一、为什么需要哨兵1.1 主从架构的痛点1.2 哨兵的作用二、哨兵的核心功能2.1 监控Monitoring2.2 通知Notification2.3 自动故障转移Automatic Failover2.4 配置提供者Configuration Provider三、哨兵配置详解3.1 哨兵配置文件3.2 配置参数说明3.3 quorum配置详解3.4 启动哨兵四、哨兵选举原理4.1 领导者哨兵选举4.2 新主节点选举五、故障转移详细流程5.1 完整故障转移流程5.2 客户端感知六、踩坑提醒七、哨兵监控与运维7.1 常用命令7.2 监控指标7.3 运维建议八、面试高频考点考点1哨兵如何判断主节点下线考点2哨兵如何选举新主节点考点3哨兵的数量如何配置考点4什么是脑裂如何解决九、参考资料十、互动话题一、为什么需要哨兵1.1 主从架构的痛点实际场景某公司Redis主节点在凌晨3点宕机运维人员收到告警后手动切换主从整个过程耗时30分钟期间服务不可用造成严重的业务损失。主从架构存在的问题问题说明单点故障主节点宕机后无法写入人工干预故障切换需要人工操作切换时间长人工响应慢服务中断时间长配置变更切换后需要修改应用配置1.2 哨兵的作用Redis Sentinel提供以下功能功能说明监控持续检查主从节点是否正常运行通知节点故障时通知管理员或其他应用自动故障转移主节点故障时自动选举新主节点配置提供者为客户端提供当前主节点地址仲裁者多个哨兵共同决策避免误判┌─────────────────────────────────────────────────────────┐ │ Sentinel Cluster │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │Sentinel-1│ │Sentinel-2│ │Sentinel-3│ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ └─────────────┼─────────────┘ │ │ │ 监控 投票 │ └─────────────────────┼───────────────────────────────────┘ │ ┌────────────┼────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Master │ │ Slave1 │ │ Slave2 │ └──────────┘ └──────────┘ └──────────┘二、哨兵的核心功能2.1 监控Monitoring哨兵定期向主从节点发送心跳检测检测类型频率说明PING每秒检测节点是否存活INFO每10秒获取主从拓扑信息PUBLISH每2秒发布哨兵信息到__sentinel__:hello频道主观下线S_DOWN单个哨兵认为节点下线配置down-after-milliseconds客观下线O_DOWN多数哨兵认为主节点下线触发故障转移流程2.2 通知Notification哨兵可以通过以下方式通知故障# 订阅哨兵频道 SUBSCRIBE __sentinel__:hello # 订阅故障转移事件 SUBSCRIBE switch-master SUBSCRIBE sdown SUBSCRIBE odown2.3 自动故障转移Automatic Failover故障转移流程┌──────────────────────────────────────────────────────────┐ │ 故障转移流程 │ ├──────────────────────────────────────────────────────────┤ │ 1. 哨兵检测到主节点客观下线 │ │ ↓ │ │ 2. 哨兵之间投票选举领导者哨兵 │ │ ↓ │ │ 3. 领导者哨兵从从节点中选举新主节点 │ │ ↓ │ │ 4. 其他从节点复制新主节点 │ │ ↓ │ │ 5. 更新主节点配置通知客户端 │ │ ↓ │ │ 6. 旧主节点恢复后变为从节点 │ └──────────────────────────────────────────────────────────┘2.4 配置提供者Configuration Provider客户端连接哨兵获取主节点地址# 客户端请求主节点地址 SENTINEL get-master-addr-by-name mymaster # 返回 1) 192.168.1.101 2) 6379三、哨兵配置详解3.1 哨兵配置文件# sentinel.conf # 端口 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 /var/redis/sentinel # 日志级别 loglevel notice # 日志文件 logfile /var/log/redis/sentinel.log # 后台运行 daemonize yes # PID文件 pidfile /var/run/redis-sentinel.pid3.2 配置参数说明参数说明默认值quorum判断客观下线需要的哨兵数量-down-after-milliseconds主观下线时间30000msfailover-timeout故障转移超时时间180000msparallel-syncs同时复制的从节点数13.3 quorum配置详解经验之谈quorum的配置需要根据哨兵数量合理设置一般设置为哨兵数量的半数以上。quorum的作用判断主节点是否客观下线选举领导者哨兵时需要多数哨兵同意推荐配置哨兵数量quorum说明11不推荐单点故障32推荐允许1个哨兵故障53推荐允许2个哨兵故障3.4 启动哨兵# 方式一使用配置文件启动redis-sentinel /etc/redis/sentinel.conf# 方式二使用redis-server启动redis-server /etc/redis/sentinel.conf--sentinel四、哨兵选举原理4.1 领导者哨兵选举当主节点被判定为客观下线后需要选举一个领导者哨兵来执行故障转移。选举流程┌─────────────────────────────────────────────────────────┐ │ 领导者哨兵选举流程 │ ├─────────────────────────────────────────────────────────┤ │ 1. 发现主节点客观下线的哨兵成为候选者 │ │ ↓ │ │ 2. 候选者向其他哨兵发送SENTINEL is-master-down-by-addr │ │ ↓ │ │ 3. 其他哨兵收到请求后每个epoch只投票一次 │ │ ↓ │ │ 4. 获得多数票的候选者成为领导者哨兵 │ │ ↓ │ │ 5. 领导者哨兵执行故障转移 │ └─────────────────────────────────────────────────────────┘选举规则使用Raft算法进行选举每个配置纪元epoch只能投票一次获得多数票的哨兵成为领导者4.2 新主节点选举领导者哨兵从从节点中选举新主节点选举规则优先级规则说明1排除下线节点不选择已下线的从节点2排除断开时间长的节点down-after-milliseconds * 103优先级配置replica-priority值小的优先4复制偏移量slave_repl_offset大的优先5runidrunid小的优先兜底从节点配置优先级# 从节点配置 replica-priority 100 # 数值越小优先级越高0表示不参与选举五、故障转移详细流程5.1 完整故障转移流程时间线 │ │ ┌─────────────────────────────────────────────┐ │ │ 1. 哨兵检测到主节点主观下线 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 2. 多数哨兵确认主节点客观下线 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 3. 哨兵之间投票选举领导者哨兵 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 4. 领导者哨兵选择新主节点 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 5. 新主节点执行 REPLICAOF NO ONE │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 6. 其他从节点复制新主节点 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 7. 更新哨兵配置发布切换事件 │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ 8. 旧主节点恢复后变为从节点 │ │ └─────────────────────────────────────────────┘ ▼5.2 客户端感知客户端通过以下方式感知主节点变化方式一订阅事件# 订阅主节点切换事件 SUBSCRIBE switch-master # 收到消息格式 # switch-master # mymaster # 192.168.1.100 6379 # 旧主节点 # 192.168.1.101 6379 # 新主节点方式二主动查询# 获取当前主节点地址 SENTINEL get-master-addr-by-name mymaster方式三连接池自动发现// Jedis示例SetStringsentinelsnewHashSet();sentinels.add(192.168.1.100:26379);sentinels.add(192.168.1.101:26379);sentinels.add(192.168.1.102:26379);JedisSentinelPoolpoolnewJedisSentinelPool(mymaster,sentinels);Jedisjedispool.getResource();// 自动获取当前主节点六、踩坑提醒踩坑提醒脑裂问题问题描述网络分区导致主节点与哨兵隔离哨兵选举出新主节点但旧主节点仍在接收写入导致数据不一致。┌─────────────────────────────────────────────────────────┐ │ 网络分区 │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ │ ┌─────────────┐ │ │ │ 旧 Master │ │ │ 新 Master │ │ │ │ (隔离区) │ │ │ (多数区) │ │ │ └─────────────┘ │ └─────────────┘ │ │ │ │ │ │ │ ▼ │ ▼ │ │ ┌─────────────┐ │ ┌─────────────┐ │ │ │ Client │ │ │ Client │ │ │ │ (写入旧主) │ │ │ (写入新主) │ │ │ └─────────────┘ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘解决方案# 主节点配置 # 至少有1个从节点才能写入 min-replicas-to-write 1 # 从节点延迟不超过10秒 min-replicas-max-lag 10配置说明如果从节点数量不足或延迟过高主节点拒绝写入防止网络分区时旧主节点继续接收写入恢复后旧主节点的数据会被新主节点覆盖踩坑提醒哨兵数量不足问题描述哨兵数量为2个时一个哨兵故障后无法进行故障转移无法达到多数票。解决方案哨兵数量至少3个建议奇数个3、5、7哨兵部署在不同服务器上踩坑提醒配置文件覆盖问题描述哨兵运行时会自动修改配置文件记录主从拓扑变化。如果手动修改配置文件可能被覆盖。解决方案哨兵配置文件需要可写权限修改配置后重启哨兵使用SENTINEL RESET命令重置配置七、哨兵监控与运维7.1 常用命令# 查看主节点信息 SENTINEL master mymaster # 查看从节点列表 SENTINEL replicas mymaster # 查看哨兵列表 SENTINEL sentinels mymaster # 获取主节点地址 SENTINEL get-master-addr-by-name mymaster # 检查主节点是否下线 SENTINEL is-master-down-by-addr 192.168.1.100 6379 # 强制故障转移 SENTINEL failover mymaster # 重置哨兵配置 SENTINEL RESET mymaster7.2 监控指标指标说明告警阈值master_link_status主从连接状态downslave_repl_offset从节点复制偏移量与主节点差距大s_down主观下线触发告警o_down客观下线触发告警num-other-sentinels其他哨兵数量少于预期7.3 运维建议建议说明哨兵数量至少3个奇数个部署位置不同服务器跨机房部署监控告警监控主从状态、复制延迟配置备份定期备份哨兵配置文件测试演练定期进行故障转移演练八、面试高频考点考点1哨兵如何判断主节点下线答案两步判断主观下线S_DOWN单个哨兵在down-after-milliseconds时间内未收到主节点PONG响应标记为主观下线客观下线O_DOWN当主观下线的哨兵数量达到quorum配置值标记为客观下线触发故障转移哨兵1: 主观下线 ────┐ 哨兵2: 主观下线 ────┼─── 客观下线 (quorum2) 哨兵3: 正常 ────┘考点2哨兵如何选举新主节点答案选举规则按优先级排除不健康节点下线或断开时间长的节点优先级配置replica-priority值小的优先复制偏移量slave_repl_offset大的优先数据最新runidrunid小的优先兜底规则配置示例# 从节点配置 replica-priority 100 # 优先级数值越小越优先考点3哨兵的数量如何配置答案哨兵数量quorum容错能力说明110不推荐210不推荐321推荐532推荐原则哨兵数量 ≥ 3且为奇数quorum 哨兵数量 / 2 1允许故障的哨兵数量 哨兵数量 - quorum考点4什么是脑裂如何解决答案脑裂问题网络分区导致旧主节点与多数哨兵隔离哨兵选举出新主节点但旧主节点仍在接收写入造成数据不一致。解决方案# 主节点配置 min-replicas-to-write 1 # 至少有1个从节点才能写入 min-replicas-max-lag 10 # 从节点延迟不超过10秒原理网络分区后旧主节点失去从节点连接配置条件不满足旧主节点拒绝写入避免数据不一致九、参考资料Redis官方文档 - Sentinel十、互动话题你的生产环境哨兵是如何部署的遇到过什么问题如何设计一个跨机房的哨兵架构需要考虑哪些因素哨兵故障转移过程中客户端如何保证写入不丢失欢迎在评论区分享你的经验和见解恭喜你完成了Redis系列文章的学习希望这个系列对你的Redis学习和面试有所帮助