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

什么是哨兵集群?

Redis 哨兵(Sentinel)是 Redis 高可用架构的智能大脑。它不存储数据,只做一件事:监控主从集群,并在主库宕机时自动投票选新主库

解决的问题

主从复制虽然实现了读写分离和数据备份,但有一个致命缺陷:主库挂了没有自动切换机制。需要人工登录服务器执行 SLAVEOF NO ONE 操作,这个过程中服务会中断。

哨兵模式解决了三个核心问题:

  1. 监控(Monitoring)—— 不断检查主库和从库是否正常运行
  2. 通知(Notification)—— 当被监控的 Redis 实例出现问题时,哨兵可以通知管理员
  3. 自动故障转移(Automatic Failover)—— 主库宕机时自动选择一个从库升级为新主库,并通知其他从库复制新主库

与普通主从集群的对比

特性 普通主从复制 哨兵模式
读写分离 ✅ 支持 ✅ 支持
数据热备份 ✅ 从库全量复制 ✅ 从库全量复制
自动故障转移 ❌ 需要手动干预 自动切换
主库宕机恢复时间 数分钟~数小时(人工) 10~30秒(自动)
部署复杂度 ⭐ 低 ⭐⭐ 中
额外资源消耗 3 个哨兵节点(轻量)

核心概念(必读)

在动手之前,先理解 3 个关键机制,否则看日志会一头雾水。

主观下线(SDOWN)

单个哨兵自己发现 ping 不通主库了,它单方面觉得主库挂了。这叫主观下线,只是个人判断,不一定准确(可能只是网络抖动)。

客观下线(ODOWN)

超过半数(quorum)的哨兵都认为主库挂了,形成共识。此时哨兵群确认主库确实宕机,准备开始故障转移。

Quorum(法定人数)

本文配置 3 个哨兵且 quorum=2。这意味着只要有 2 个哨兵认为主库挂了,就触发自动切换。既保证了可靠性,又防止了 1 个哨兵因网络抖动导致误切换。

Tilt 模式(躺平保护)

这是哨兵最容易被忽略但极其重要的保护机制。 当哨兵检测到系统时钟出现异常跳跃,或事件循环耗时超过 2 秒时,会主动进入 Tilt(躺平)模式

  • Tilt 模式下暂停所有故障检测和故障转移操作
  • 持续约 30 秒后自动退出
  • 目的是防止因系统时间不准或网络卡顿导致脑裂(错误地切换主库)

环境准备

前置知识

本文基于已搭建好的一主两从集群(见 Redis主从集群搭建实战)。如果你还没有主从集群,请先阅读那篇文章。

当前集群拓扑

角色 服务名 容器名 端口
🟢 主库 master redis-master 6379
🟢 从库 1 replica1 redis-replica-1 6380
🟢 从库 2 replica2 redis-replica-2 6381

哨兵配置文件

config/ 目录下创建三个几乎相同的配置文件。唯一的变化是端口不同(但实际上在各自容器中都是 26379,不影响)。

config/sentinel1.conf

port 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 yes

config/sentinel2.conf / sentinel3.conf

内容完全一样,因为端口在容器内部各自隔离。

参数解读

参数 含义
mymaster 自定义名称 你给这个主从集群起的名字,哨兵通过这个名字来识别
master 6379 主库地址 Docker 网络中的服务名和端口,哨兵通过它找到主库
2 quorum 法定人数。3 个哨兵中至少 2 个同意,才触发切换
down-after-milliseconds 5000ms 哨兵 ping 主库超过 5 秒没响应就认为挂了
failover-timeout 10000ms 故障转移超时限制
parallel-syncs 1 切换后同时通知几个从库同步新主库
resolve-hostnames yes 延迟解析主机名,避免启动时因 DNS 未就绪而崩溃

更新 docker-compose.yml

在原有主从配置的基础上,追加 3 个哨兵服务。注意与 services 同级缩进:

  # ---------- 哨兵节点 1 ----------
  sentinel1:
    image: redis:7.2.4
    container_name: redis-sentinel-1
    restart: always
    ports:
      - "26379:26379"
    volumes:
      - ./config/sentinel1.conf:/usr/local/etc/redis/sentinel.conf
      - ./data/sentinel1:/data
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    depends_on:
      - master
      - replica1
      - replica2
    networks:
      - redis-net

  # ---------- 哨兵节点 2 ----------
  sentinel2:
    image: redis:7.2.4
    container_name: redis-sentinel-2
    restart: always
    ports:
      - "26380:26379"
    volumes:
      - ./config/sentinel2.conf:/usr/local/etc/redis/sentinel.conf
      - ./data/sentinel2:/data
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    depends_on:
      - master
      - replica1
      - replica2
    networks:
      - redis-net

  # ---------- 哨兵节点 3 ----------
  sentinel3:
    image: redis:7.2.4
    container_name: redis-sentinel-3
    restart: always
    ports:
      - "26381:26379"
    volumes:
      - ./config/sentinel3.conf:/usr/local/etc/redis/sentinel.conf
      - ./data/sentinel3:/data
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    depends_on:
      - master
      - replica1
      - replica2
    networks:
      - redis-net

启动哨兵并验证监控状态

启动集群

docker-compose up -d

验证哨兵是否成功监控主库

进入任一哨兵容器查看主库状态:

docker exec -it redis-sentinel-1 redis-cli -p 26379
> SENTINEL master mymaster

关键输出解读:

字段 健康值 含义
flags master 主库在线
num-slaves 2 检测到 2 个从库
num-other-sentinels 2 发现另外 2 个哨兵伙伴
quorum 2 法定人数配置生效

查看从库列表

> 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

第一步:查询主库当前 IP

docker inspect redis-master | grep IPAddress

输出示例:"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-compose restart sentinel1 sentinel2 sentinel3

第四步:验证哨兵已监控正确的 IP

docker exec -it redis-sentinel-1 redis-cli -p 26379 SENTINEL master mymaster

确认 ip 字段为 172.23.0.2

执行故障转移

第一步:开一个终端实时查看哨兵日志

docker logs redis-sentinel-1 --tail 30 -f

第二步:另一个终端执行停库

docker stop 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   ← 切换成功!

第四步:查询新主库

docker exec -it redis-sentinel-1 redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster

返回新的主库 IP 和端口(如 172.23.0.4:6380)。

验证新主库写入

# 进入新主库写入数据
docker exec -it redis-replica-2 redis-cli -p 6381
127.0.0.1:6381> set status "failover-success"
OK
127.0.0.1:6381> get status
"failover-success"

恢复旧主库,观察自动降级

docker start redis-master
# 等待 5 秒后查看它的角色
docker exec -it redis-master redis-cli -p 6379 INFO replication

你会惊讶地发现,旧主库的 role 已经变成了 slave,自动认了新主库做大哥。这就是哨兵在后台自动 CONFIG REWRITE 的神奇之处。

完整的切换流程原理

你亲手验证了 Redis 自动故障转移的完整闭环

  1. 监控:哨兵们通过 PING 检测到主库失联(+sdown
  2. 投票:由于配置了 quorum=2,其他哨兵也报告连不上,触发 +odown
  3. 选举:哨兵们内部选出一个领导者+elected-leader
  4. 挑选:领导者从从库中挑选数据最新的(slave-repl-offset 最大)执行升主
  5. 切换:执行 REPLICAOF NO ONE 提升为新的主库(+switch-master
  6. 重配置:通知其他从库去复制新主库,并强制旧主库重新上线后成为从库

大坑总结与反思

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 问题。

posted @ 2026-08-08 22:00  PC2005-cloud  阅读(24)  评论(0)    收藏  举报