ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Redis学习笔记:哨兵集群实战,自动故障转移与高可用架构完整指南

2026/8/8 22:06:47 拓冰建站 浏览量
Redis学习笔记:哨兵集群实战,自动故障转移与高可用架构完整指南 本文首发于 栏轩·阁欢迎访问阅读原文获取更好的阅读体验。什么是哨兵集群Redis 哨兵Sentinel是 Redis 高可用架构的智能大脑。它不存储数据只做一件事监控主从集群并在主库宕机时自动投票选新主库。解决的问题主从复制虽然实现了读写分离和数据备份但有一个致命缺陷主库挂了没有自动切换机制。需要人工登录服务器执行SLAVEOF NO ONE操作这个过程中服务会中断。哨兵模式解决了三个核心问题监控Monitoring—— 不断检查主库和从库是否正常运行通知Notification—— 当被监控的 Redis 实例出现问题时哨兵可以通知管理员自动故障转移Automatic Failover—— 主库宕机时自动选择一个从库升级为新主库并通知其他从库复制新主库与普通主从集群的对比特性普通主从复制哨兵模式读写分离✅ 支持✅ 支持数据热备份✅ 从库全量复制✅ 从库全量复制自动故障转移❌ 需要手动干预✅自动切换主库宕机恢复时间数分钟~数小时人工10~30秒自动部署复杂度⭐ 低⭐⭐ 中额外资源消耗无3 个哨兵节点轻量核心概念必读在动手之前先理解 3 个关键机制否则看日志会一头雾水。主观下线SDOWN单个哨兵自己发现 ping 不通主库了它单方面觉得主库挂了。这叫主观下线只是个人判断不一定准确可能只是网络抖动。客观下线ODOWN超过半数quorum的哨兵都认为主库挂了形成共识。此时哨兵群确认主库确实宕机准备开始故障转移。Quorum法定人数本文配置 3 个哨兵且quorum2。这意味着只要有 2 个哨兵认为主库挂了就触发自动切换。既保证了可靠性又防止了 1 个哨兵因网络抖动导致误切换。Tilt 模式躺平保护这是哨兵最容易被忽略但极其重要的保护机制。当哨兵检测到系统时钟出现异常跳跃或事件循环耗时超过 2 秒时会主动进入Tilt躺平模式Tilt 模式下暂停所有故障检测和故障转移操作持续约 30 秒后自动退出目的是防止因系统时间不准或网络卡顿导致脑裂错误地切换主库环境准备前置知识本文基于已搭建好的一主两从集群见 Redis主从集群搭建实战。如果你还没有主从集群请先阅读那篇文章。当前集群拓扑角色服务名容器名端口 主库masterredis-master6379 从库 1replica1redis-replica-16380 从库 2replica2redis-replica-26381哨兵配置文件在config/目录下创建三个几乎相同的配置文件。唯一的变化是端口不同但实际上在各自容器中都是 26379不影响。config/sentinel1.confport 26379 sentinel monitor mymaster master 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1 sentinel resolve-hostnames yesconfig/sentinel2.conf / sentinel3.conf内容完全一样因为端口在容器内部各自隔离。参数解读参数值含义mymaster自定义名称你给这个主从集群起的名字哨兵通过这个名字来识别master 6379主库地址Docker 网络中的服务名和端口哨兵通过它找到主库2quorum法定人数。3 个哨兵中至少 2 个同意才触发切换down-after-milliseconds5000ms哨兵 ping 主库超过 5 秒没响应就认为挂了failover-timeout10000ms故障转移超时限制parallel-syncs1切换后同时通知几个从库同步新主库resolve-hostnamesyes延迟解析主机名避免启动时因 DNS 未就绪而崩溃更新 docker-compose.yml在原有主从配置的基础上追加 3 个哨兵服务。注意与services同级缩进# ---------- 哨兵节点 1 ----------sentinel1:image:redis:7.2.4container_name:redis-sentinel-1restart:alwaysports:-26379:26379volumes:-./config/sentinel1.conf:/usr/local/etc/redis/sentinel.conf-./data/sentinel1:/datacommand:redis-sentinel /usr/local/etc/redis/sentinel.confdepends_on:-master-replica1-replica2networks:-redis-net# ---------- 哨兵节点 2 ----------sentinel2:image:redis:7.2.4container_name:redis-sentinel-2restart:alwaysports:-26380:26379volumes:-./config/sentinel2.conf:/usr/local/etc/redis/sentinel.conf-./data/sentinel2:/datacommand:redis-sentinel /usr/local/etc/redis/sentinel.confdepends_on:-master-replica1-replica2networks:-redis-net# ---------- 哨兵节点 3 ----------sentinel3:image:redis:7.2.4container_name:redis-sentinel-3restart:alwaysports:-26381:26379volumes:-./config/sentinel3.conf:/usr/local/etc/redis/sentinel.conf-./data/sentinel3:/datacommand:redis-sentinel /usr/local/etc/redis/sentinel.confdepends_on:-master-replica1-replica2networks:-redis-net启动哨兵并验证监控状态启动集群docker-composeup-d验证哨兵是否成功监控主库进入任一哨兵容器查看主库状态dockerexec-itredis-sentinel-1 redis-cli-p26379SENTINEL master mymaster关键输出解读字段健康值含义flagsmaster主库在线num-slaves2检测到 2 个从库num-other-sentinels2发现另外 2 个哨兵伙伴quorum2法定人数配置生效查看从库列表SENTINEL replicas mymaster会列出两个从库的 IP、端口、复制偏移量和连接状态。测试故障转移核心实验问题使用容器名 DNS 无法触发故障转移如果哨兵配置中使用的是主机名master执行docker stop redis-master后哨兵日志会出现Failed to resolve hostname master sdown master mymaster 172.23.0.2 6379 tilt #tilt mode entered原因Docker 的内部 DNS 解析master主机名时有 1-2 秒的超时重试导致哨兵的事件循环被阻塞超过 2 秒触发Tilt 躺平保护模式。在 Tilt 模式下哨兵禁止执行故障转移导致切换永远无法完成形成tilt→-tilt→ 又tilt的死循环。解决方案把主机名改成固定 IP第一步查询主库当前 IPdockerinspect redis-master|grepIPAddress输出示例IPAddress: 172.23.0.2第二步修改 3 个哨兵配置文件将sentinel monitor mymaster master 6379 2改为sentinel monitor mymaster 172.23.0.2 6379 2只要不执行docker-compose down不会删除网络Docker 会一直将这个 IP 分配给该容器。第三步重启哨兵docker-composerestart sentinel1 sentinel2 sentinel3第四步验证哨兵已监控正确的 IPdockerexec-itredis-sentinel-1 redis-cli-p26379SENTINEL master mymaster确认ip字段为172.23.0.2。执行故障转移第一步开一个终端实时查看哨兵日志dockerlogs redis-sentinel-1--tail30-f第二步另一个终端执行停库dockerstop redis-master第三步观察日志因为哨兵现在直接通过 IP 探测主库docker stop会让 TCP 连接瞬间收到 RST 包毫秒级返回失败完全不会触发 Tilt。你会看到清晰的切换流程sdown master mymaster 172.23.0.2 6379 odown master mymaster 172.23.0.2 6379 #quorum 2/2 new-epoch 1 try-failover master mymaster vote-for-leader ... elected-leader master mymaster failover-state-select-slave master switch-master mymaster 172.23.0.2 6379 172.23.0.4 6380 ← 切换成功第四步查询新主库dockerexec-itredis-sentinel-1 redis-cli-p26379SENTINEL get-master-addr-by-name mymaster返回新的主库 IP 和端口如172.23.0.4:6380。验证新主库写入# 进入新主库写入数据dockerexec-itredis-replica-2 redis-cli-p6381127.0.0.1:6381setstatusfailover-successOK127.0.0.1:6381get statusfailover-success恢复旧主库观察自动降级dockerstart redis-master# 等待 5 秒后查看它的角色dockerexec-itredis-master redis-cli-p6379INFO replication你会惊讶地发现旧主库的role已经变成了slave自动认了新主库做大哥。这就是哨兵在后台自动CONFIG REWRITE的神奇之处。完整的切换流程原理你亲手验证了 Redis 自动故障转移的完整闭环监控哨兵们通过 PING 检测到主库失联sdown投票由于配置了quorum2其他哨兵也报告连不上触发odown选举哨兵们内部选出一个领导者elected-leader挑选领导者从从库中挑选数据最新的slave-repl-offset最大执行升主切换执行REPLICAOF NO ONE提升为新的主库switch-master重配置通知其他从库去复制新主库并强制旧主库重新上线后成为从库大坑总结与反思Docker DNS 超时导致 Tilt 死循环这是 Docker Sentinel 最常见的坑。主机名master的 DNS 解析有 1-2 秒超时延迟导致哨兵事件循环阻塞触发 Tilt 保护。修复方案是使用固定 IP或添加sentinel resolve-hostnames yes。知识图谱层级组件掌握程度数据存储1 主 2 从✅ 熟练偏移量、全量/增量同步自动切换3 哨兵✅ 刚跑通SDOWN/ODOWN/投票选举/Tilt️待攻克Redis Cluster分片❓ 准备就绪总结本文从一主两从集群出发逐步搭建了 3 节点哨兵高可用架构并亲手验证了自动故障转移流程。核心收获哨兵配置sentinel monitor、quorum、超时参数的含义故障转移 6 步流程SDOWN → ODOWN → 选举 → 选从 → 切换 → 重配置Tilt 保护机制Docker DNS 超时导致的死循环及修复方案IP 与主机名的选择生产环境中建议使用 IP 以避免 DNS 抖动以上是 Redis 哨兵模式的完整动手实践。下一阶段可以学习Redis Cluster分片集群——它将哨兵的故障转移能力内嵌到每个节点中并使用哈希槽实现数据水平扩展且完全抛弃 DNS 解析从根本上避免本文遇到的 Tilt 问题。