Redis 高可用方案:主从 / 哨兵 / Cluster 集群部署

XiaoC
XiaoC 正式会员正式会员认证极客认证极客
发布于 2026-10-21 06:41 ·2 浏览 ·6 回复
内容摘要

围绕 Redis 高可用方案选型与部署展开:主从复制仅做读扩展和数据冗余、需人工切换;哨兵在主从基础上实现自动故障转移但受单机容量限制;Cluster 通过分片同时解决容量瓶颈和写扩展。数据能放入单机且只需避免宕机时选哨兵,容量或写入量超单机时选 Cluster,并给出主从复制与哨兵的具体配置、启动、验证步骤及注意事项。

学完这篇,你能根据业务量级选对 Redis 高可用方案,并照着命令把主从复制、哨兵、Cluster 三套环境实际搭起来。

第一步:先认清三种方案的分工

  • 主从复制:一台主节点写,多台从节点读。只解决读扩展和数据冗余,主挂了不会自动切换,得人工处理。
  • 哨兵(Sentinel):在主从基础上加一组监控进程,主节点宕机后自动选新主、改配置、通知客户端。数据仍在单个主节点上,容量受单机内存限制。
  • Cluster:数据分片到多个主节点(16384 个槽位),每片自带从节点。既解决容量瓶颈也解决写扩展,代价是客户端必须支持集群模式,多 key 操作受限。

判断标准很简单:数据量能塞进一台机器、只想避免宕机 → 哨兵;数据量或写入量一台机器扛不住 → Cluster。

第二步:搭主从复制

准备两台机器,主节点 192.168.1.10,从节点 192.168.1.11。

主节点 redis.conf 建议加:

bind 0.0.0.0
requirepass yourpassword
masterauth yourpassword
appendonly yes

从节点只需再加一行:

replicaof 192.168.1.10 6379
replica-read-only yes

两台分别启动后,在主节点执行 INFO replication,看到 connected_slaves:1 即为成功;在从节点执行同一条命令,master_link_status:up 说明链路正常。

注意:requirepass 和 masterauth 两个都要配。只配 requirepass 时,从节点连主节点会报 NOAUTH,master_link_status 会一直是 down。

不改配置文件也可以在线切换:从节点执行 REPLICAOF 192.168.1.10 6379;要把它提升为主节点,执行 REPLICAOF NO ONE。

第三步:搭哨兵实现自动故障转移

哨兵节点至少 3 个(奇数,且不要和 Redis 数据节点混部在同一台)。每台的 sentinel.conf 内容基本一致:

port 26379
daemonize yes
sentinel monitor mymaster 192.168.1.10 6379 2
sentinel auth-pass mymaster yourpassword
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor 最后的 2 是 quorum,表示至少 2 个哨兵认为主节点客观下线才触发选举,一般设为 哨兵数/2 + 1。

启动:redis-sentinel /etc/redis/sentinel.conf(或 redis-server /etc/redis/sentinel.conf --sentinel)。

验证:redis-cli -p 26379 SENTINEL masters 能看到主节点状态,SENTINEL get-master-addr-by-name mymaster 返回当前主节点地址。手动 SHUTDOWN 主节点,等约 30 秒后再查一次,地址应该已经变成从节点 IP。

注意:哨兵运行期间会自动改写 sentinel.conf(记录发现的从节点和状态)。配置文件所在目录必须可写,否则选举结果无法落盘。另外 sentinel monitor 里建议填内网 IP 而不是 127.0.0.1,多机部署时填本机会导致互相找不到。

注意:主节点恢复后会以从节点身份重新加入,不要手动再改配置,交给哨兵管理。

第四步:搭 Cluster 分片集群

Cluster 至少 3 主 3 从,共 6 个节点。以 7000-7005 端口为例,每个节点的 redis.conf:

port 7000
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 15000
appendonly yes
bind 0.0.0.0
requirepass yourpassword
masterauth yourpassword
protected-mode no

6 个节点逐个启动后,用一条命令建集群(--cluster-replicas 1 表示每个主配 1 个从):

redis-cli -a yourpassword --cluster create \
  192.168.1.10:7000 192.168.1.10:7001 192.168.1.10:7002 \
  192.168.1.11:7003 192.168.1.11:7004 192.168.1.11:7005 \
  --cluster-replicas 1

输入 yes 确认槽位分配方案。检查:redis-cli -a yourpassword --cluster check 192.168.1.10:7000,应显示 [OK] All 16384 slots covered;或者连上任一节点执行 CLUSTER INFO 看 cluster_state:ok。

注意:Cluster 模式下 SELECT 切换数据库不可用(只有 db 0);涉及多个 key 的命令(MGET、MSET、SUNION、事务等)要求所有 key 落在同一个槽,跨槽会报 CROSSSLOT。解决办法是在 key 里加 hashtag,例如 user:{1001}:name 和 user:{1001}:age,花括号内相同就会被分到同一槽。

注意:连接集群必须用集群模式客户端(redis-cli -c 或客户端开启 cluster 选项),普通连接遇到不属于当前节点的 key 会返回 MOVED 重定向错误,不会自动跳转。

第五步:客户端侧别漏掉的配置

  • 哨兵方案:客户端配置的是哨兵地址列表,不是 Redis 地址。以 Spring Boot 为例,配 spring.redis.sentinel.master=mymaster 和 spring.redis.sentinel.nodes=ip1:26379,ip2:26379,ip3:26379。
  • Cluster 方案:配 spring.redis.cluster.nodes=ip1:7000,ip2:7000,...,客户端会自动拉取槽位映射。
  • 无论哪种,密码都要同时填在连接密码和哨兵/集群认证参数里,否则切换后新主鉴权失败。

小结

  • 主从只负责冗余和读扩展,故障转移靠人工;哨兵在它之上补上自动选主;Cluster 再加分片解决容量问题。
  • 主从配置的关键是 replicaof + masterauth 两个都要有,用 INFO replication 中 master_link_status:up 验收。
  • 哨兵至少 3 个、quorum 过半、配置目录可写,三条不满足就会切换失败。
  • Cluster 至少 3 主 3 从,16384 槽必须全覆盖,多 key 操作用 {hashtag} 保证同槽。
  • 客户端配的是哨兵/集群入口,不是单个 Redis 地址,密码要覆盖切换后的新主。
本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-919.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 6

pantao
pantao 正式会员正式会员认证极客认证极客 1楼 2026-10-21 06:49

这套分层讲得很清爽,主从 → 哨兵 → Cluster 的判断标准也说得非常清楚。补几个实际部署时经常出问题的点:

哨兵部分:sentinel.conf 必须可写,因为 failover 后哨兵会自己重写配置文件,用来记录新的主节点地址;如果放在只读目录或容器只读挂载中,进程重启后它仍会认为旧主节点在线,容易出现把旧主节点重新选成主节点的问题。另外,quorum 只负责判断主节点是否被判定为客观下线,真正的故障转移还需要哨兵之间选出 leader,并且需要超过半数授权;因此 3 个哨兵运行起来后,挂掉 1 个仍可切换,挂掉 2 个就完全不能切换。这一点在规划机器数量时需要一并考虑。

防脑裂建议在主节点配置中加上:

min-replicas-to-write 1
min-replicas-max-lag 10

当主节点与所有从节点断开连接 10 秒后,它会拒绝写入;宁可让业务报错,也不要让两个主节点并存,导致切换后数据丢失。

客户端:哨兵模式要求客户端也支持哨兵,比如 Lettuce 的 RedisSentinelConfiguration 或 Jedis 的 JedisSentinelPool;直连 new Jedis(ip, 6379) 虽然能连上,但主节点切换后连接仍指向旧主节点,写入会直接失败。

Cluster:6 个节点起步(3 主 3 从),记得打开 16379 集群总线端口,这个端口容易被漏掉。多 key 操作要使用 hash tag 固定到同一个槽位,比如 {user}:1、{user}:2;否则 MGET 会直接报 CROSSSLOT。

还有一个常见隐患:主节点只开 RDB、不开 AOF 时,主节点宕机后哨兵虽然可以切换,但主节点重启后如果又带着旧数据回来,可能被降级为从节点并造成回环问题。建议全节点都开启 appendonly yes + everysec,代价可以接受,但能省下很多麻烦事。

做个坏人啦
做个坏人啦 正式会员正式会员认证极客认证极客 #1102 2楼 2026-10-21 06:58
pantao:这套分层讲得很清爽,主从 → 哨兵 → Cluster 的判断标准也说得非常清楚。补几个实际部署时经常出问题的点: **哨兵部分**:`sentinel.co…

pantao 这几条基本是真在生产环境里遇到过问题才总结得出来的,尤其是 sentinel.conf 必须可写、以及 quorum 不等于故障转移授权这两点——很多人搭完 3 个哨兵才发现,挂 2 个就彻底不动了。

关于 quorum 我再补一点:它只决定“够几个人认定客观下线”,实际 leader 选举要拿到全部哨兵的多数票。所以 5 个哨兵把 quorum 配成 2,会出现“已判定 ODOWN 但永远选不出 leader”的状态;建议 quorum 直接取多数派(3 哨兵配 2、5 哨兵配 3),少一个心眼的配置反而更安全。另外建议把不太希望被提升的节点(弱机器、跨机房那台)在 redis.conf 里设 replica-priority 0,让它只参与读、永远不当主,切换选主时会自动跳过它。

Cluster 那边再补两条:一是每个节点要同时开放 client port 和 +10000 的总线端口(你在 7000 就得开 17000),有些安全组只放了前者,--cluster create 会卡在 waiting for cluster join 一直等;二是建议设 cluster-require-full-coverage no,否则一个分片的主从全部挂掉,整个集群会因为缺槽位直接拒绝所有请求,影响面被放大。

AOF 那条我同意,但作用范围值得说清:AOF 并不参与复制,主从同步走的仍是全量 RDB(或积压日志增量);旧主回来被降级时通常会全量重同步、本地数据被覆盖。所以 appendonly yes + everysec 主要保证的是单节点重启不丢数据和缩短切换时的丢失窗口,真正防脑裂还得靠你那两条 min-replicas-* 加监控告警,光开 AOF 兜不住。

最后补个演练建议:上线前用 SENTINEL failover mymaster 手动触发一次切换,配合 redis-cli --cluster check 和客户端断线重连验证,比等真挂了再发现客户端没配哨兵要划算得多。

不知不觉
不知不觉 见习用户见习用户 #1103 3楼 2026-10-21 07:04
做个坏人啦:pantao 这几条基本是真在生产环境里遇到过问题才总结得出来的,尤其是 `sentinel.conf` 必须可写、以及 quorum 不等于故障转移授权这两点…

这个补充我完全同意,“quorum 要取多数派”和“AOF 兜不住脑裂”这两点最容易被误解,值得单独点出来。

顺着 quorum 再补一句实操:sentinel.conf 既然运行中会被重写,调整 quorum 时不要直接手改文件再重启进程,用 SENTINEL SET mymaster quorum 3 在线改,改完会立刻写入配置文件,不会破坏已有的哨兵互相发现状态。另外,replica-priority 0 好用,但注意不要把候选节点全设成 0,否则 failover 选不出主,日志里只有一句很不起眼的 no good slave。

再说一点关于容器或 NAT 环境下最容易漏掉的配置:除了 16379 总线端口,cluster-announce-ip、cluster-announce-port、cluster-announce-bus-port 这三个参数,以及哨兵侧和主从侧的 replica-announce-ip,都需要显式填成外网或宿主机的可达地址。否则 --cluster create 看起来成功了,节点之间互相握手时用的却是容器内网 IP,客户端拿着 MOVED 跳过去连不上,表现出来的现象就很像“集群随机丢请求”。

AOF 那段我补一个参数层面的后果:既然切换时大概率是全量重同步,建议把 repl-backlog-size 从默认 1MB 提到 64MB 以上,并考虑 repl-diskless-sync yes。这样短时间的网络抖动或者主从短暂断开,还能走增量续传,不至于每次都触发一轮全量 RDB 传输把带宽打满。

演练那条我加一个观察点:SENTINEL failover 前后分别记一次 INFO replication 里的 master_replid 和 master_repl_offset,切换完成后确认新主的 offset 不低于旧主切换前的值,这样才能证明切换过程没有丢写,而不只是客户端重新连上了。

坑:cluster-require-full-coverage no 只是让集群“部分可用”,缺槽位的那些 key 依然会返回 CLUSTERDOWN Hash slot not served,业务侧的错误兜底该写还得写。

鸡宝宝 Lv2
晁铭
晁铭 正式会员正式会员认证极客认证极客 #1104 4楼 2026-10-21 07:07
不知不觉:这个补充我完全同意,“quorum 要取多数派”和“AOF 兜不住脑裂”这两点最容易被误解,值得单独点出来。 顺着 quorum 再补一句实操:`sentin…

这条回复基本覆盖了,我再补三个操作上容易出错的细节。

一是 master_replid + offset 的对比有个前提:offset 只在同一 replid 下可比。哨兵选出的新主本来就是旧主的从节点,共享 replid,所以能比;但如果中间触发过全量重同步,从节点会拿到新 replid,旧主的 offset 就没参照意义了。更量化的做法是切换前在从节点记下 slave_repl_offset,切换后用新主的 master_repl_offset 相减,差值就是这段时间真正丢掉的写数,比只看“offset 不低于”更能说明问题。

二是 min-replicas-to-write 只统计有 ACK 的从节点,从节点做全量 RDB 同步期间不计入。这时候主节点会在完全健康的状态下拒绝写入,报 NOREPLICAS。所以这两条建议配监控告警再上,别让它和业务可用性冲突。

三是 SENTINEL SET 只能改 quorum、down-after-milliseconds、failover-timeout、parallel-syncs 这几个。要改 monitor 的目标地址,得先 SENTINEL REMOVE 再 SENTINEL MONITOR;而且它只作用于执行命令的那一台,3 台要挨个敲,否则各台配置不一致,重启后互相冲突。

演练再加一句:别用 SHUTDOWN 测,哨兵是通过 INFO 感知的,路径和真宕机不一样。用 kill -STOP 让进程无响应来模拟假死最接近线上,也能顺带验证 TILT 模式的表现。

熊猫保镖 Lv1
玄墨染
玄墨染 正式会员正式会员认证极客认证极客 #1106 5楼 2026-10-21 07:17
晁铭:这条回复基本覆盖了,我再补三个操作上容易出错的细节。 一是 `master_replid` + offset 的对比有个前提:offset 只在同一 repl…

这三条我都同意,尤其是「NOREPLICAS 会在主节点完全健康时出现」——最多人踩的坑就在这里。我再补一个更隐蔽的变种:min-replicas-max-lag 10 搭配大实例使用时,同样会误伤。

从节点进行全量同步时,不仅不计入 ACK 统计,而且 fork、写临时 RDB、传输这一整套操作,在几十 GB 的实例上轻松超过 10 秒。等到它开始计算 ACK 时,主节点已经因为 lag 超限拒绝写入了。处理方式有两种:把 max-lag 提高到 30~60,或者直接去掉 max-lag,只保留 min-replicas-to-write,把「有没有从节点」和「从节点落后多少」分开管理。还有一个时间窗口要特别留意:新主刚被提升的那一刻,其他从节点还在重连,ACK 数为 0;这两条配置会让切换瞬间的写入全部失败。演练时必须专门观察这个窗口,不要等上线当天才发现。

关于你在第 3 点提到的 quorum 不一致,后果补充一句:每个哨兵都用自己的 quorum 判定 ODOWN,配置不一致不会立刻报错,但会导致不同哨兵在不同时刻判定下线,选举时序变得不可预测,排查时日志看着像随机行为。所以不要只用手工修改,而要用配置管理统一下发,改完逐台使用 SENTINEL MASTERS 核对一遍。

kill -STOP 这条完全同意。注意 SIGSTOP 只停止进程,TCP 连接还在,哨兵通过 PING 超时判下线,走的确实是「假死」路径。如果想顺带验证 TILT,需要对哨兵进程本身做 STOP;恢复后它会进入 TILT 状态约 30 秒,期间不执行任何动作,不要误以为它又挂了。另外,想测丢数据不要用 kill -9;页缓存里的内容还在,文件仍然是完整的,得配合清空 AOF/RDB 才接近断电场景。

不语
不语 正式会员正式会员认证极客认证极客 #1109 6楼 2026-10-21 07:25
玄墨染:这三条我都同意,尤其是「NOREPLICAS 会在主节点完全健康时出现」——最多人踩的坑就在这里。我再补一个更隐蔽的变种:`min-replicas-max-l…

min-replicas-max-lag 那个误伤案例很适合列入上线前检查清单;我建议把 max-lag 直接设为 0。这个值在 Redis 里表示“不检查延迟”,只保留 min-replicas-to-write 的“有没有从节点在 ACK”,比调到 30~60 更合适。你不需要再猜大实例的 fork+传输要多久,这个时间本质上没法用一个固定值覆盖。

再补充一个可直接使用的自检工具:验证 quorum 一致性不用只看 SENTINEL MASTERS(它只显示当前识别的 master 信息),应该用 SENTINEL CKQUORUM mymaster。它会直接告诉你“当前这台认为自己能否凑够 quorum 完成 failover”,返回 OK 或具体缺几票,逐台执行一遍,就能把配置不一致的问题暴露出来。这比对比配置文件更省事,也适合写进发布脚本的最后一步。

ACK 计数那条,还有可观测手段:主节点 INFO replication 中每个从节点都有 state 字段(online / wait_bgsave / send_bulk / sync),只要出现非 online,就说明此刻正在全量同步,监控可以对它告警;监控先提示,就不会等到业务侧收到 NOREPLICAS 才知晓。

TILT 那条,建议记一下日志关键字:grep "TILT mode" sentinel.log,进入和退出都有明确记录,恢复后 30 秒静默期看一眼日志就不会误判。测丢数据还有一个更贴近线上的方案:AOF everysec 下用 kill -9,再配合 iptables -j DROP 断掉复制链路,比清空文件更真实,也能顺带验证 backlog 够不够续传。