Redis 从零到一(06):主从复制、哨兵与 Cluster 集群
2026-10-12 09:40:00

适合人群:单机 Redis 用得飞起,但一想到”它挂了怎么办、数据大了怎么办”就没底的同学。
一句话主线:主从解决读扩展和数据冗余,哨兵解决自动故障转移,Cluster 解决容量与写入的水平扩展。

一、单机 Redis 的两个天花板

  1. 可用性:单点。进程挂了、机器坏了,缓存全灭,流量全部砸向数据库(缓存雪崩的最猛形态)
  2. 容量与写性能:单机内存上限就是数据上限;10 万 QPS 的写入天花板,一个实例再顶也顶不住

三套方案依次解题:主从 → 哨兵 → Cluster。

图1:主从复制的数据同步流程

二、主从复制:一主多从,读写分离

配置一行

1
2
3
4
# 在从节点上执行,或写进配置
REPLICAOF 192.168.1.10 6379

# 主节点负责写,从节点只读(默认 replica-read-only yes)

数据流是单向的:主节点接收写命令,异步复制给所有从节点;读请求可以分摊给从节点。

全量同步:第一次连上时

  1. 从节点发送 PSYNC ? -1(我啥也没有)
  2. 主节点回 +FULLRESYNC <replid> <offset>,开始 BGSAVE 生成 RDB
  3. 主节点把 RDB 发给从节点,从节点清空自己后载入
  4. 这期间主节点的新写命令存在**复制积压缓冲区(repl_backlog)**里,载入完再补发给从节点

增量同步:断线重连时

从节点短暂断线后重连,带上自己已同步到的 offset:

  • offset 还在 repl_backlog 范围内 → 只补发缺的那一段(部分重同步)
  • 断太久、缓冲区已被覆盖 → 退化成全量同步(代价大,所以 backlog 默认 1MB,写入大的集群要调大)

两个必须知道的特性:

  • 异步复制:主节点不等从节点确认就回客户端 OK——极端情况下主宕机会丢最后一小段数据(这也是上一篇分布式锁”主从切换丢锁”的根源)
  • 从节点过期策略:从节点不会主动删过期 key,等主库的删除命令同步过来,保证主从一致

三、哨兵(Sentinel):自动故障转移

主从有个明显短板:主节点挂了,谁来把某个从节点提升为主? 人工半夜爬起来敲命令不现实。哨兵就是干这个的独立进程:

  • 监控:持续 ping 主从节点
  • 通知:出问题时通知运维/程序
  • 自动故障转移:主挂了,自动完成”选新主 + 其他从库改挂 + 通知客户端”
  • 配置中心:客户端先连哨兵问”现在谁是主”,而不是写死地址

故障转移的完整流程

假设部署 3 个哨兵(哨兵自身也要奇数个、至少 3 个,避免哨兵自己单点):

  1. 主观下线(sdown):哨兵 A ping 主节点,超时了——“我觉得它挂了”
  2. 客观下线(odown):A 问其他哨兵”你们也觉得挂了吗?”,达到 quorum(配置的法定数,如 2/3)才判定真挂——防止单个哨兵因自身网络抖动误判
  3. 选举 leader 哨兵:哨兵之间投票选出一名主持人(Raft 思想:先到先得的多数派投票)
  4. 挑选新主:按优先级(replica-priority)→ 复制 offset 最新的 → runid 最小的。优先级 0 的从节点永远不会被选
  5. 执行切换:选中的从节点 SLAVEOF NO ONE 升为主;其余从节点改挂新主;旧主回来后也变成新主的从
  6. 通知客户端:客户端通过订阅哨兵的频道感知主节点变更

一个最小的哨兵配置:

1
2
3
4
5
# sentinel.conf
port 26379
sentinel monitor mymaster 192.168.1.10 6379 2 # quorum = 2
sentinel down-after-milliseconds mymaster 5000 # 5 秒无响应判主观下线
sentinel failover-timeout mymaster 60000

Java 侧(Lettuce/Redisson)都原生支持哨兵模式,配置里写哨兵地址列表即可,客户端自动发现当前主节点。

主从 + 哨兵 = 高可用,但容量和写入仍是单主扛着——这就轮到 Cluster。

四、Cluster:分片,水平扩展的正解

核心设计:16384 个槽位(slot)

Redis Cluster 不按”节点数”切分数据,而是先把 key 空间切成 16384 个 slot,再把 slot 分配给各主节点:

1
2
# key 落在哪个槽:对 key 做 CRC16 再取模
slot = CRC16(key) mod 16384

3 主节点的集群(官方最小规模要求 6 节点:3 主 3 从):

  • 节点 A:slot 0 ~ 5460
  • 节点 B:slot 5461 ~ 10922
  • 节点 C:slot 10923 ~ 16383

图2:Redis Cluster 的槽位分片与 MOVED 重定向

面试必问:为什么是 16384? 两个原因:心跳包里要带节点负责的 slot 位图,16384 个 bit = 2KB,再大网络开销就浪费了(CRC16 本身能产生 65536 个值);同时官方建议集群不超过 1000 个主节点,16384 个槽足够分。

客户端怎么找到正确的节点:MOVED / ASK

客户端可以连任意节点,节点对每条命令做检查:

  • key 属于自己 → 正常执行
  • 不属于自己 → 回 MOVED <slot> <ip:port>,客户端重定向到正确节点(聪明的客户端会缓存 slot 映射表,直接打对节点)
  • 特殊场景迁移中(slot 正在从 A 搬到 B):先回 ASK,客户端去 B 上临时执行这一条,不改缓存映射

节点间通信:Gossip 协议

集群里的节点通过 Gossip(PING/PONG/MEET/FAIL 消息)互相交换状态:谁在线、谁挂了、slot 分布如何。没有中心化的协调节点,每个节点都是对等的。cluster-node-timeout(默认 15 秒)内多数节点都联系不上某节点,就把它标记 FAIL。

高可用内置:每个主节点挂从

Cluster 不需要单独的哨兵进程——每个主节点配一个从节点,某主挂了,集群里过半主节点同意后,它的从自动升级(故障转移内置在集群协议里)。

集群的代价(必知)

  • 多 key 命令受限:MSET、MGET、Lua 多 key 操作要求所有 key 在同一个 slot。跨 slot 的 key 用 hash tag 强制同槽:{user:1001}:name、{user:1001}:cart——大括号里的内容才参与 slot 计算
  • 事务与 Lua 只能在单 key 空间内用
  • 数据库只有 db0(单机 16 个 db 在集群里不存在)
  • 运维复杂度上升:扩缩容要迁移 slot(redis-cli --cluster reshard)

快速搭一个本地实验集群

1
2
3
4
5
6
7
8
9
10
11
12
# 一键创建 3 主 3 从的本地集群(6 个端口 7000-7005)
for port in 7000 7001 7002 7003 7004 7005; do
mkdir -p /tmp/redis-cluster/$port
redis-server --port $port --cluster-enabled yes \
--cluster-config-file /tmp/redis-cluster/$port/nodes.conf \
--appendonly yes --daemonize yes
done

redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

redis-cli -c -p 7000 # -c 开启集群模式(自动跟随 MOVED)

五、三种方案怎么选

维度 主从 哨兵 Cluster
解决什么 读扩展、数据冗余 自动故障转移 容量 + 写入的水平扩展
写能力 单主 单主 分片到多主
容量上限 单机内存 单机内存 多机内存之和
额外组件 无 哨兵进程 x>=3 无(协议内置)
客户端复杂度 低 中(发现主节点) 中高(slot 路由)

选型路径:

  1. 数据量单机放得下(< 10GB 级)、纯缓存:主从 + 哨兵,简单成熟
  2. 数据量或写入吞吐超单机:Cluster
  3. 云上托管:阿里云 Tair、AWS ElastiCache 直接选带主从/集群的规格,故障转移都替你做了

系列总结

六篇走完,回头看 Redis 的知识地图:

  • 01 数据结构:选对结构,性能差十倍
  • 02 持久化:RDB 快照与 AOF 日志的权衡,混合持久化是生产答案
  • 03 缓存三大问题:穿透/击穿/雪崩对症下药,一致性用 Cache Aside
  • 04 过期与淘汰:惰性 + 定期删除,内存满了按 LRU/LFU 淘汰
  • 05 分布式锁:从 SETNX 到 Redisson 看门狗的三次进化
  • 06 高可用:主从 → 哨兵 → Cluster 的三级火箭

Redis 的所有设计都围绕同一组矛盾:内存很快但有限、单线程很快但怕慢命令、复制提高可用性但引入一致性窗口。理解了这三组矛盾,Redis 的面试题和线上事故,你都能顺着推出答案。

上一页
2026-10-12 09:40:00
下一页