Redis Sentinel指南

1. 架构概览

Redis Sentinel 提供自动故障转移、服务发现和配置管理。推荐最少部署 3 个 Sentinel 实例,因为仲裁投票需要多数派(quorum)才能判定主节点下线并选举领导者。2 个 Sentinel 无法在网络分区时达成多数派共识,可能导致脑裂。

┌──────────────┐ │ Sentinel-1 │ :26379 │ (投票节点) │ └──────┬───────┘ │ ┌──────────────┼──────────────┐ │ │ │ ┌──────┴───────┐ ┌───┴──────┐ ┌─────┴────────┐ │ Sentinel-2 │ │ Master │ │ Sentinel-3 │ │ (投票节点) │ │ :6379 │ │ (投票节点) │ └──────────────┘ └────┬─────┘ └──────────────┘ ┌────┴─────┐ ┌────┴───┐ ┌───┴────┐ │Replica1│ │Replica2│ │ :6380 │ │ :6381 │ └────────┘ └────────┘ quorum=2: 3个Sentinel中至少2个同意才能触发故障转移
Sentinel 实例应部署在独立的物理机或可用区,避免单点故障。每个 Sentinel 独立判断主节点状态,分布在不同故障域可以保证即使一台宕机,仲裁仍可达成。

2. 快速搭建

步骤 1:安装 Redis

# Ubuntu/Debian sudo apt update && sudo apt install redis-server -y # CentOS/RHEL sudo yum install epel-release -y && sudo yum install redis -y # macOS brew install redis # Verify redis-server --version

步骤 2:配置主节点

# /etc/redis/redis-master.conf bind 0.0.0.0 port 6379 requirepass YourStrongPassword masterauth YourStrongPassword dir /var/lib/redis appendonly yes appendfsync everysec

步骤 3:配置副本节点

# /etc/redis/redis-replica1.conf (replica2 similar, port 6381) bind 0.0.0.0 port 6380 replicaof 192.168.1.10 6379 masterauth YourStrongPassword requirepass YourStrongPassword dir /var/lib/redis-replica1 appendonly yes

步骤 4:配置 Sentinel 节点

# /etc/redis/sentinel.conf (repeat on 3 machines) port 26379 daemonize yes logfile /var/log/redis/sentinel.log dir /tmp sentinel monitor mymaster 192.168.1.10 6379 2 sentinel auth-pass mymaster YourStrongPassword sentinel down-after-milliseconds mymaster 5000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 60000 sentinel deny-scripts-reconfig yes

步骤 5:启动所有服务

# Start master redis-server /etc/redis/redis-master.conf # Start replicas redis-server /etc/redis/redis-replica1.conf redis-server /etc/redis/redis-replica2.conf # Start sentinels (on each sentinel machine) redis-sentinel /etc/redis/sentinel.conf # Verify replication redis-cli -a YourStrongPassword INFO replication # Verify sentinel redis-cli -p 26379 SENTINEL master mymaster

3. sentinel.conf 完整参考

指令 默认值 说明
sentinel monitor <name> <ip> <port> <quorum>-监控一个主节点。quorum 是判定 ODOWN 所需最少 Sentinel 数。建议值:N/2+1(3节点设2,5节点设3)
sentinel down-after-milliseconds30000主节点多久无响应后判定为 SDOWN。生产环境建议 5000-10000ms,过低会导致误报
sentinel parallel-syncs1故障转移后同时重新同步的副本数。值越大恢复越快,但同步期间副本不可读
sentinel failover-timeout180000故障转移超时(ms)。超时后 Sentinel 认为故障转移失败,允许其他 Sentinel 重试。至少设为 2x replication timeout
sentinel auth-pass-主节点密码。设置后 Sentinel 用此密码连接主节点和副本
sentinel auth-user-Redis 6+ ACL 用户名,配合 auth-pass 使用
sentinel deny-scripts-reconfigyes禁止通过 SENTINEL SET 修改通知脚本路径。生产环境必须开启以防止安全风险
sentinel notification-script-状态变化时执行的脚本路径。脚本接收事件类型和描述作为参数
sentinel client-reconfig-script-故障转移后执行的脚本,参数包含新旧主节点地址。可用于更新 DNS 或负载均衡器
sentinel resolve-hostnamesnoRedis 6.2+,允许使用主机名代替 IP,适配容器和 DNS 环境

4. Sentinel API 命令

命令 说明
SENTINEL masters列出所有受监控的主节点及其状态
SENTINEL master <name>返回指定主节点的详细信息(IP、端口、标志、副本数等)
SENTINEL replicas <name>列出主节点的所有副本
SENTINEL sentinels <name>列出监控该主节点的其他 Sentinel 实例
SENTINEL get-master-addr-by-name <name>返回当前主节点的 IP 和端口(客户端用于服务发现)
SENTINEL ckquorum <name>检查当前是否有足够的 Sentinel 在线以达成仲裁
SENTINEL failover <name>手动触发故障转移(不需要其他 Sentinel 同意)
SENTINEL reset <pattern>重置匹配的主节点状态,清除已知副本和 Sentinel 列表
SENTINEL flushconfig将运行时配置强制写入 sentinel.conf
SENTINEL pending-scripts列出待执行的通知脚本队列
SENTINEL myid返回当前 Sentinel 的唯一 ID

5. 故障转移流程

SDOWN ODOWN 领导者选举 副本选择 提升 重新配置
阶段 详细说明
SDOWN主观下线:单个 Sentinel 在 down-after-milliseconds 内未收到主节点的有效 PING 回复。这是单方面判断,不触发故障转移。
ODOWN客观下线:当 quorum 数量的 Sentinel 都报告 SDOWN 时,状态升级为 ODOWN。通过 SENTINEL is-master-down-by-addr 命令互相确认。
领导者选举使用 Raft 算法的变体,Sentinel 互相投票选出一个领导者执行故障转移。需要多数派(N/2+1)投票。每个 epoch 只投一次票,防止重复选举。
副本选择领导者 Sentinel 依据优先级(replica-priority,值越小优先级越高,0 表示不参与选举)、复制偏移量(数据最新)、Run ID(字典序最小)的顺序选择最优副本。
提升向选中的副本发送 REPLICAOF NO ONE,使其变为独立主节点。等待其确认角色切换完成。
重新配置所有其他副本执行 REPLICAOF <new-master> 切换到新主节点。Sentinel 更新自身配置并通过 Pub/Sub 发布 +switch-master 事件通知客户端。
故障转移期间会有短暂的写入不可用窗口(通常 1-3 秒)。异步复制意味着最近写入的数据(尚未同步到副本的部分)可能会丢失。可通过 min-replicas-to-writemin-replicas-max-lag 限制数据丢失窗口。

6. 客户端连接

Node.js (ioredis)

const Redis = require("ioredis"); const client = new Redis({ sentinels: [ { host: "sentinel1", port: 26379 }, { host: "sentinel2", port: 26379 }, { host: "sentinel3", port: 26379 }, ], name: "mymaster", password: "YourStrongPassword", sentinelPassword: "SentinelPass", // Redis 6+ sentinel ACL role: "master", enableTLSForSentinelMode: false, sentinelRetryStrategy: (times) => Math.min(times * 100, 3000), }); client.on("error", (err) => console.error("Redis error:", err));

Python (redis-py)

from redis.sentinel import Sentinel sentinel = Sentinel( [("sentinel1", 26379), ("sentinel2", 26379), ("sentinel3", 26379)], socket_timeout=0.5, sentinel_kwargs={"password": "SentinelPass"}, password="YourStrongPassword", ) master = sentinel.master_for("mymaster", socket_timeout=0.5) replica = sentinel.slave_for("mymaster", socket_timeout=0.5) master.set("key", "value") print(replica.get("key")) # read from replica

Java (Lettuce)

RedisURI uri = RedisURI.Builder .sentinel("sentinel1", 26379, "mymaster") .withSentinel("sentinel2", 26379) .withSentinel("sentinel3", 26379) .withPassword("YourStrongPassword".toCharArray()) .build(); RedisClient client = RedisClient.create(uri); StatefulRedisMasterReplicaConnection<String, String> conn = MasterReplica.connect(client, StringCodec.UTF8, uri); conn.setReadFrom(ReadFrom.REPLICA_PREFERRED);

Go (go-redis)

import "github.com/redis/go-redis/v9" client := redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: "mymaster", SentinelAddrs: []string{"sentinel1:26379", "sentinel2:26379", "sentinel3:26379"}, SentinelPassword: "SentinelPass", Password: "YourStrongPassword", DB: 0, DialTimeout: 5 * time.Second, ReadTimeout: 3 * time.Second, WriteTimeout: 3 * time.Second, })

7. Sentinel vs Redis Cluster

特性 Sentinel Redis Cluster
主要用途高可用(HA)HA + 数据分片
数据分片不支持,单主节点存储全部数据自动分片到 16384 个哈希槽
数据容量受限于单机内存线性扩展
最小节点数3 Sentinel + 1M + 2R = 63 主 + 3 副本 = 6
故障转移时间~5-15s~1-5s
客户端复杂度需要 Sentinel-aware 客户端需要 Cluster-aware 客户端,处理 MOVED/ASK 重定向
多键操作全部支持(单主节点)仅同槽位键支持,需使用 {hash_tag}
适用场景数据集 < 25GB,需要简单 HA数据集大、需要水平扩展

8. 生产最佳实践

网络与部署拓扑

将 3 或 5 个 Sentinel 部署在不同的可用区或机架。避免将 Sentinel 与 Redis 数据节点部署在同一台机器——当该机器宕机时,你会同时丢失投票者和被监控者。使用奇数个 Sentinel(3 或 5),偶数个无法提高容错能力却增加复杂度。

仲裁 (Quorum) 配置

quorum 控制 ODOWN 判定阈值,但故障转移选举需要多数派(N/2+1)。3 节点 quorum=2:容忍 1 个 Sentinel 故障。5 节点 quorum=3:容忍 2 个故障,适合跨 3 个数据中心的部署。

监控与告警

# Subscribe to all Sentinel events for monitoring redis-cli -p 26379 PSUBSCRIBE '*' # Key events to alert on: # +sdown / -sdown — SDOWN state changes # +odown / -odown — ODOWN state changes # +switch-master — master address changed (failover completed) # +failover-end — failover finished # -failover-abort-* — failover aborted (investigate!) # Check quorum health periodically redis-cli -p 26379 SENTINEL ckquorum mymaster

安全:TLS + ACL

# sentinel.conf — TLS (Redis 6+) tls-port 26380 port 0 tls-cert-file /etc/redis/tls/sentinel.crt tls-key-file /etc/redis/tls/sentinel.key tls-ca-cert-file /etc/redis/tls/ca.crt tls-replication yes tls-auth-clients optional # Redis 6+ ACL: create sentinel-specific user # On master/replica redis.conf: user sentinel-user on >SentinelPass ~* +ping +info +multi +exec +subscribe +psubscribe +publish +slaveof +replicaof +config|rewrite +config|set +client|setname +client|kill +client|getname

数据安全配置

# On master redis.conf — reject writes if too few replicas are connected # This prevents data loss during network partitions min-replicas-to-write 1 min-replicas-max-lag 10 # seconds

9. 故障排查

问题 原因与解决方案
脑裂 (Split-Brain) 网络分区导致两个主节点同时存在。预防:设置 min-replicas-to-write 1,被隔离的旧主节点因无法连接到副本而拒绝写入。确保 Sentinel 部署在至少 3 个网络区域。
SDOWN 频繁切换 Sentinel 反复在 SDOWN 和正常之间切换。通常由 down-after-milliseconds 设置过低或网络延迟抖动引起。解决:增大超时到 10000ms+,检查 Sentinel 与主节点之间的网络质量。
故障转移未触发 可能原因:(1) 在线 Sentinel 不足以达到 quorum——用 SENTINEL ckquorum 验证。(2) failover-timeout 内已有一次失败的故障转移,需等待冷却。(3) 没有可用副本(所有副本 priority=0 或断开)。
故障转移后复制延迟 新主节点的副本需要进行全量同步(RDB 传输)。缓解:确保 repl-diskless-sync yes(Redis 6.0+默认),增大 repl-backlog-size 以支持部分重同步,设置 parallel-syncs 1 避免所有副本同时同步导致带宽饱和。
Sentinel 配置漂移 Sentinel 会自动重写 sentinel.conf(添加已发现的副本和 Sentinel)。如果用配置管理工具(Ansible/Puppet)覆盖该文件,会导致状态不一致。解决:只管理初始配置,运行后让 Sentinel 自治。

10. 常见问题

Sentinel 可以监控多个 Redis 主节点吗?

可以。在 sentinel.conf 中添加多个 sentinel monitor 行即可,每个主节点使用不同的名称。每组主节点可以有独立的 quorum、超时和密码配置。这在需要为多个独立应用提供 HA 保障时非常实用。

使用 Docker/Kubernetes 部署 Sentinel 需要注意什么?

容器环境的主要挑战是 NAT 和端口映射。Sentinel 会将自己发现的 IP 广播给其他 Sentinel,但在 Docker 中这可能是容器内部 IP。解决方案:(1) 使用 sentinel announce-ipsentinel announce-port 声明外部可达地址。(2) Redis 6.2+ 开启 sentinel resolve-hostnames yes 支持 DNS 名称。(3) 在 Kubernetes 中推荐使用 StatefulSet + Headless Service。

Sentinel 故障转移期间会丢失数据吗?

是的,因为 Redis 使用异步复制。主节点接受写入后在后台将数据同步到副本。如果主节点在同步完成前崩溃,尚未传播的写入会丢失。通过 min-replicas-to-write + min-replicas-max-lag 可以缩小丢失窗口:主节点在没有足够低延迟副本时会拒绝写入,将最大数据丢失限制在 max-lag 秒内。

quorum 和 majority 有什么区别?

quorum 是检测 ODOWN(客观下线)所需的最小 Sentinel 同意数,可在 sentinel monitor 中自定义。majority 是 N/2+1,用于领导者选举阶段。即使 quorum 设为 1,故障转移仍然需要多数派 Sentinel 在线才能选出领导者。例如 5 个 Sentinel + quorum=2:2 个同意就标记 ODOWN,但需要 3 个在线才能选举领导者并执行故障转移。

如何实现零停机升级 Redis 版本?

推荐滚动升级流程:(1) 先升级所有副本节点(逐个重启)。(2) 手动触发 SENTINEL failover mymaster 将主节点切换到已升级的副本。(3) 升级旧主节点(现在是副本)。(4) 最后逐个升级 Sentinel 节点。整个过程中服务保持可用,仅在故障转移时有 1-3 秒写入中断。

Sentinel 适合多大规模的 Redis 部署?

Sentinel 适用于单主节点场景,数据量受限于单机内存(通常 25-100GB)。如果需要超过单机内存的容量或需要写入水平扩展,应使用 Redis Cluster。Sentinel 可以同时监控多组主节点(每组独立故障转移),但每组仍然是单主节点架构。

💬 留言讨论