Redis 主从复制可以持续产生数据副本,但主库失联后,副本仍然保持只读。要恢复写服务,系统还需要回答三个问题:主库是否真的故障、由谁主持切换,以及哪个副本应该成为新主库。

Redis Sentinel 就是普通主从复制之上的高可用控制平面。它不保存业务数据,也不转发业务请求,而是持续监控 Redis 节点,在满足条件时协调自动故障转移,并告诉客户端当前主库在哪里。

Sentinel 提供的四项能力

官方通常把 Sentinel 的职责概括为四类:

  • 监控:检查主库、副本和其他 Sentinel 是否可达。
  • 通知:把节点异常和故障转移事件交给运维系统。
  • 服务发现:回答某个监控主库当前位于哪个地址。
  • 故障转移:主库确认故障后,选择副本晋升并重建复制关系。

典型的三服务器拓扑如下:

node-1                 node-2                 node-3
Redis 主库             Redis 副本             Redis 副本
:6379                  :6379                  :6379
Sentinel :26379        Sentinel :26379        Sentinel :26379
      └────────── 共同监控 mymaster ──────────┘

三个 Sentinel 构成投票和协调平面,三个 Redis 节点构成数据平面。这两个平面不能混为一谈:Sentinel 全部正常,不代表 Redis 数据一定完整;Redis 副本全部在线,也不代表一定能够完成自动选主。

Sentinel 如何发现拓扑

最初只需要告诉 Sentinel 主库地址和监控名称,例如:

sentinel monitor mymaster 192.168.10.11 6379 2

Sentinel 连接主库后,可以从主库的复制信息中发现副本。多个 Sentinel 还会通过 Redis 发布订阅频道交换自己的地址、运行 ID 和主库配置纪元,从而逐渐形成一致的监控视图。

监控名称 mymaster 是逻辑服务名。应用使用 Sentinel 客户端时,配置的是这个名称和多个 Sentinel 地址,而不是把某一台 Redis 的 IP 永久写死。

主观下线与客观下线

一次网络超时不足以证明主库真的故障。Sentinel 把故障判断分成两层。

主观下线:SDOWN

当一个 Sentinel 在 down-after-milliseconds 时间内无法得到主库的有效响应,它会从自己的视角把主库标记为主观下线。

“主观”意味着这是单点观察。可能是主库故障,也可能只是这个 Sentinel 与主库之间的网络中断。

客观下线:ODOWN

标记主观下线后,Sentinel 会询问其他 Sentinel 是否也认为主库不可达。当同意数量达到配置的 quorum,主库才会被标记为客观下线。

Sentinel-1:我联系不到主库 ── SDOWN

      ├─ 询问 Sentinel-2:同意
      └─ 询问 Sentinel-3:同意

同意数达到 quorum ────────── ODOWN

副本和其他 Sentinel 也可能被标记为主观下线,但客观下线和自动故障转移只针对被监控的主库。

quorum 不等于多数派

这是 Sentinel 最容易混淆的地方。

  • quorum:需要多少 Sentinel 同意,才能把主库判定为客观下线。
  • 多数派授权:某个 Sentinel 要成为本轮故障转移领导者,必须获得 Sentinel 多数派支持。

假设共有 5 个 Sentinel,quorum 配置为 2。两个 Sentinel 同意后可以形成 ODOWN,但执行故障转移仍然需要至少 3 个 Sentinel 构成多数派。quorum 决定“是否认为主库故障”,多数派决定“是否有权执行切换”。

三 Sentinel、quorum 为 2 是常见的最小拓扑。一台 Sentinel 不可用时,剩余两台仍有机会完成判断和授权;只剩一台时,即使它能看到 Redis 副本,也不能独自完成安全的自动故障转移。

领导者是怎样选出来的

主库客观下线后,多个 Sentinel 可能同时希望主持故障转移。Sentinel 使用配置纪元区分不同轮次,并在每个纪元中投票选出一个领导者。

可以把过程简化为:

  1. Sentinel 发现主库 ODOWN,发起一个新的故障转移纪元。
  2. 它请求其他 Sentinel 在该纪元中支持自己。
  3. 每个 Sentinel 在同一纪元只支持一个候选者。
  4. 获得多数派授权的 Sentinel 成为领导者。
  5. 如果没有候选者及时获得授权,本轮超时后会在新纪元重试。

领导者只负责协调本轮故障转移,它不会永久成为集群管理中心。Sentinel 没有一个固定不变的主控节点。

新主库不是随机选择的

领导者会排除不适合晋升的副本,例如长时间断线或明确禁止晋升的节点。对于剩余候选者,选择大致会考虑:

  1. replica-priority,值越小优先级越高,配置为 0 表示不参与晋升。
  2. 副本处理到的复制偏移量,通常越新越优先。
  3. Redis 运行 ID,用于在前面条件相同时产生稳定顺序。

因此,不应该在运维脚本中假定“node-2 一定成为新主库”。角色是运行时状态,应通过 Sentinel 查询当前结果。

一次完整故障转移

选出目标副本后,领导者会逐步重建拓扑:

  1. 向目标副本发送提升命令,使其停止复制并成为主库。
  2. 等待新主库角色生效。
  3. 让其他副本改为跟随新主库。
  4. 更新 Sentinel 维护的主库地址和配置纪元。
  5. 通过事件通知其他 Sentinel 和客户端。
  6. 旧主库恢复后,把它改成当前主库的副本。
旧主库故障


SDOWN → ODOWN → 选举领导者 → 选择副本 → 提升新主

                                         ├─ 重配其他副本
                                         └─ 更新主库发现信息

恢复后的旧主库不会自动“抢回”主库角色。让已经完成的拓扑保持稳定,可以避免反复切换造成抖动和额外全量同步。

客户端如何使用 Sentinel

Sentinel 不代理 Redis 流量。应用仍然直接连接 Redis,只是在建立或恢复连接时通过 Sentinel 查询主库地址。

客户端通常需要配置:

  • 至少两个或三个 Sentinel 地址。
  • 监控主库名称,例如 mymaster
  • Redis 认证信息,以及 Sentinel 自身的认证信息。
  • 连接重试和故障转移后的重连策略。

如果应用仍把 192.168.10.11:6379 写死,Sentinel 即使成功切换主库,应用也不会自动转向新地址。部署 Sentinel 的同时必须确认所用客户端明确支持 Sentinel 模式。

一致性与脑裂边界

Sentinel 建立在异步复制之上,不能消除主库已确认但尚未复制的写入。旧主库与多数 Sentinel 失联、却仍能被部分客户端访问时,还可能继续接受写入;新主库产生后,两边形成短暂双主。

可以使用以下措施降低风险,但不能把系统变成强一致:

  • 通过网络和代理确保应用总是使用 Sentinel 发现的主库。
  • 设置 min-replicas-to-writemin-replicas-max-lag,副本不足时限制旧主写入。
  • 合理分布 Redis 和 Sentinel,避免共同故障域。
  • 根据业务恢复点目标配置 AOF、RDB 和独立备份。

三服务器最小部署

示例使用三台 Linux 服务器:

服务器地址Redis 初始角色
node-1192.168.10.11主库
node-2192.168.10.12副本
node-3192.168.10.13副本

三台服务器各运行一个 Redis 和一个 Sentinel,统一使用 redis:8.8.0。node-1 的 redis.conf 包含基础认证和持久化:

bind 0.0.0.0
protected-mode yes
port 6379
requirepass RedisBlog_ChangeMe_2026!
masterauth RedisBlog_ChangeMe_2026!
appendonly yes
appendfsync everysec
dir /data
daemonize no

node-2 和 node-3 额外配置初始主库,并把 replica-announce-ip 分别设置为自己的 IP:

replicaof 192.168.10.11 6379
replica-read-only yes
replica-announce-ip 192.168.10.12
replica-announce-port 6379

三台服务器的 sentinel/sentinel.conf 使用相同监控参数,但 sentinel announce-ip 必须写当前服务器自己的地址:

bind 0.0.0.0
protected-mode yes
port 26379
daemonize no
dir /tmp

requirepass RedisBlog_ChangeMe_2026!
sentinel monitor mymaster 192.168.10.11 6379 2
sentinel auth-pass mymaster RedisBlog_ChangeMe_2026!
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel announce-ip 192.168.10.11
sentinel announce-port 26379

Sentinel 会动态重写自己的配置文件,因此挂载目录必须可写。三台服务器使用相同的 compose.yml

services:
  redis:
    image: redis:8.8.0
    container_name: redis-sentinel-node
    restart: unless-stopped
    network_mode: host
    command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
    volumes:
      - ./redis.conf:/usr/local/etc/redis/redis.conf:ro
      - ./data:/data

  sentinel:
    image: redis:8.8.0
    container_name: redis-sentinel
    restart: unless-stopped
    network_mode: host
    command: ["redis-sentinel", "/usr/local/etc/redis-sentinel/sentinel.conf"]
    volumes:
      - ./sentinel:/usr/local/etc/redis-sentinel

先启动 node-1,再启动 node-2 和 node-3:

docker compose up -d

验证监控与故障转移

在任意节点查询当前主库:

docker exec -e REDISCLI_AUTH='RedisBlog_ChangeMe_2026!' \
  redis-sentinel redis-cli -p 26379 \
  SENTINEL get-master-addr-by-name mymaster

初始结果应指向 192.168.10.11:6379。还应检查 Sentinel 是否发现两个副本和另外两个 Sentinel:

docker exec -e REDISCLI_AUTH='RedisBlog_ChangeMe_2026!' \
  redis-sentinel redis-cli -p 26379 SENTINEL replicas mymaster

docker exec -e REDISCLI_AUTH='RedisBlog_ChangeMe_2026!' \
  redis-sentinel redis-cli -p 26379 SENTINEL sentinels mymaster

在 node-1 停止 Redis、保留 Sentinel:

docker compose stop redis

等待超过故障判断时间后,从 node-2 或 node-3 再次查询主库地址。结果应变为其中一个副本,而不是继续指向 node-1。恢复 node-1 后,通过 INFO replication 可以观察到它作为当前主库的副本重新加入。

Sentinel 适合什么场景

Sentinel 适合数据仍能放入单个主库、写入入口仍然只有一个,但需要自动故障转移的系统。它保留普通 Redis 的数据模型,客户端改造通常小于 Cluster。

Sentinel 不提供数据分片,也不会提升单个主库的写容量。如果容量或写吞吐已经超过单机边界,继续阅读 Redis Cluster:哈希槽、客户端路由与故障转移。如果只想先理解复制本身,可以回到 Redis 主从复制:从全量同步到人工故障切换

参考资料