跳到主要内容

Redis 集群方案

问题

Redis 的高可用方案有哪些?主从复制、哨兵和 Cluster 的区别是什么?Redis Cluster 如何实现数据分片?

答案

Redis 部署架构演进

主从复制

一主多从,主写从读,通过 binlog 同步。

同步流程

阶段说明
全量同步从节点首次连接:主节点 BGSAVE 生成 RDB → 发送给从节点 → 从节点加载 RDB → 期间的增量命令通过 buffer 补发
增量同步正常运行时:主节点将写命令传播到从节点(命令传播)
部分重同步从节点断线重连:通过 repl_backlog 缓冲区只同步断线期间的命令(2.8+)
配置主从
# 从节点 redis.conf
replicaof 192.168.1.100 6379

主从复制的问题

  • 主节点故障需手动切换
  • 只解决了读扩展,写能力受限于单主
  • 不提供自动故障转移

哨兵模式(Sentinel)

哨兵是 Redis 高可用的解决方案,通过监控主从节点,自动完成故障转移。

故障转移流程

  1. 主观下线:单个 Sentinel 认为主节点不可达(ping 超时)
  2. 客观下线:超过 quorum 数量的 Sentinel 都认为主节点不可达
  3. Leader 选举:Sentinel 之间通过 Raft 选出一个 Leader 执行故障转移
  4. 选新主:从存活的从节点中按优先级、复制偏移量、ID 选出新主
  5. 切换:通知其他从节点复制新主,通知客户端连接新主
Sentinel 配置
# sentinel.conf
sentinel monitor mymaster 192.168.1.100 6379 2 # quorum=2
sentinel down-after-milliseconds mymaster 5000 # 5 秒无响应判定下线
sentinel failover-timeout mymaster 60000 # 故障转移超时 60 秒

哨兵的局限

  • 写能力仍受限于单主
  • 存储容量受限于单机内存
  • 故障转移期间有短暂不可用时间

Redis Cluster

Redis 官方的分布式方案,支持数据分片 + 高可用 + 自动故障转移

哈希槽(Hash Slot)

Redis Cluster 将数据划分为 16384 个哈希槽,分配给各主节点:

slot = CRC16(key) % 16384
特性说明
槽总数16384
分配方式平均分配或手动指定
槽迁移支持在线迁移(不停机扩缩容)
为什么是 16384 个槽

节点间通过 Gossip 协议交换槽位信息,每个节点发送的心跳包包含一个 16384 位的 bitmap(2KB)。如果用更多的槽,bitmap 更大,增加网络开销。16384 是一个在集群规模(一般不超过 1000 个节点)和网络开销之间的均衡选择。

MOVED 重定向

客户端发送命令到错误节点时,会收到 MOVED 响应:

-> GET key1
-MOVED 12345 192.168.1.102:6379

客户端应更新本地的槽-节点映射表,下次直接请求正确节点。

节点通信

Redis Cluster 使用 Gossip 协议 进行节点间通信:

消息类型说明
PING检测节点是否在线
PONG回复 PING
MEET邀请新节点加入集群
FAIL通知其他节点某节点已下线

Cluster 故障转移

与哨兵类似,但由 Cluster 节点自身完成:

  1. 从节点检测到主节点下线
  2. 从节点发起投票请求
  3. 集群中过半主节点同意
  4. 从节点晋升为主节点,接管槽位

三种方案对比

对比维度主从复制哨兵Cluster
高可用❌ 手动切换✅ 自动故障转移✅ 自动故障转移
数据分片✅ 16384 哈希槽
写扩展❌ 单主❌ 单主✅ 多主
存储扩展❌ 单机❌ 单机✅ 多机
复杂度
适用场景读多写少、开发测试中小规模高可用大规模、高并发

常见面试问题

Q1: Redis Cluster 的数据分片原理?

答案

Redis Cluster 使用哈希槽(Hash Slot) 进行数据分片:

  1. 16384 个槽,分配给集群中的各主节点
  2. 每个 key 通过 CRC16(key) % 16384 计算所属槽
  3. 客户端根据槽映射表将请求发到对应节点
  4. 如果发错了,节点返回 MOVED 重定向

扩容时通过在线槽迁移,将部分槽从旧节点迁移到新节点,无需停机。

Q2: 哨兵如何判断主节点下线?

答案

分为两个阶段:

  1. 主观下线(SDOWN):单个 Sentinel 在 down-after-milliseconds 时间内未收到主节点的有效回复,认为该节点主观下线
  2. 客观下线(ODOWN):该 Sentinel 询问其他 Sentinel,当有 quorum 数量的 Sentinel 都认为主节点下线,则判定为客观下线,触发故障转移

quorum 的建议值为 Sentinel 总数 / 2 + 1(如 3 个 Sentinel 的 quorum 设为 2)。

Q3: Cluster 模式下多 key 操作有什么限制?

答案

Redis Cluster 不支持跨槽的多 key 操作。MGETMSETPIPELINE 中包含的 key 如果分布在不同槽,会报错。

解决方案:

  1. Hash Tag:使用 {tag} 让相关 key 计算到同一个槽
# {user:1} 是 Hash Tag,这两个 key 会在同一个槽
SET {user:1}:name "张三"
SET {user:1}:age 25
MGET {user:1}:name {user:1}:age # ✅ 同槽,可以
  1. 客户端分组:按槽对 key 分组,分别发送请求后合并结果

Q4: 主从复制的全量同步和增量同步?

答案

  • 全量同步(首次连接或 backlog 丢失):主节点执行 BGSAVE 生成 RDB → 发送 RDB 给从节点 → 从节点清空数据加载 RDB → 主节点将 RDB 期间的增量命令发送给从节点
  • 增量同步(正常运行时):主节点将写命令通过 TCP 连接传播给从节点
  • 部分重同步(断线重连):从节点携带 replication offset,如果偏移量在主节点的 repl_backlog 中,只补发缺失部分;否则触发全量同步

Q5: Redis Cluster 为什么至少需要 6 个节点?

答案

Redis Cluster 要求至少 3 个主节点(故障转移投票需要过半主节点同意),每个主节点至少 1 个从节点(保证主节点故障后有从节点接管),所以最小配置是 3 主 3 从 = 6 节点

如果只有 2 个主节点,一个主节点挂了,另一个无法达到"过半"的投票条件,集群将不可用。

相关链接