Redis 集群方案有哪些?

2025年 阅读约 15 分钟 面试指南 · Redis

深入解析Redis集群方案:主从复制(全量同步RDB+增量同步replication buffer)、哨兵Sentinel(主观下线/客观下线、Leader选举)、Cluster集群(16384哈希槽、MOVED/ASK重定向、Gossip协议),附面试模拟问答。

一句话总结

Redis 集群方案演进:主从复制(读写分离、数据冗余)→ Sentinel 哨兵(自动故障转移)→ Cluster 集群(数据分片、水平扩展)。Cluster 使用 16384 个哈希槽(CRC16(key) % 16384)分配数据,节点间通过 Gossip 协议通信。客户端访问错误节点时返回 MOVED(槽已迁移)或 ASK(槽迁移中)重定向。

初级理解

三种集群方案对比

方案数据分片高可用扩展性复杂度
主从复制❌ 不分片❌ 手动切换❌ 垂直扩展
Sentinel❌ 不分片✅ 自动故障转移❌ 垂直扩展
Cluster✅ 哈希槽分片✅ 内置故障转移✅ 水平扩展
# 主从复制配置 # 从库配置 replicaof 192.168.1.100 6379 # 指定主库 # Sentinel 配置(sentinel.conf) sentinel monitor mymaster 192.168.1.100 6379 2 # 2 个 Sentinel 认为主库下线才触发故障转移 # Cluster 配置 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000
一句话总结:主从复制做读写分离,Sentinel 做自动故障转移,Cluster 做数据分片和水平扩展。

中级深入

主从复制 — 全量同步与增量同步

# 全量同步(首次连接或复制偏移量差距太大) # 1. 从库发送 PSYNC ? -1(请求全量同步) # 2. 主库执行 BGSAVE 生成 RDB,同时用 replication buffer 记录新命令 # 3. 主库发送 RDB 给从库 # 4. 从库加载 RDB # 5. 主库发送 buffer 中的增量命令 # 增量同步(短暂断连后重连) # 1. 从库发送 PSYNC replid offset # 2. 主库检查 replid 是否匹配 # 3. 如果 offset 在 repl_backlog_buffer 范围内 → 增量同步 # 4. 否则 → 全量同步 # repl_backlog_buffer 配置 repl-backlog-size 64mb # 环形缓冲区大小 # 越大越能容忍短暂断连

Sentinel — 故障转移流程

# 故障转移流程 # 1. 主观下线(SDOWN):单个 Sentinel 认为主库不可达 # 2. 客观下线(ODOWN):quorum 个 Sentinel 都认为主库不可达 # 3. Leader 选举:Sentinel 之间 Raft 选举一个 Leader # 4. Leader 选新主库:从从库中选一个最优的 # 选择标准:优先级 > 复制偏移量 > runid # 5. 通知其他从库复制新主库 # 6. 通知客户端新主库地址 # Sentinel 配置 sentinel monitor mymaster 192.168.1.100 6379 2 sentinel down-after-milliseconds mymaster 30000 # 30秒无响应判定下线 sentinel failover-timeout mymaster 180000 # 故障转移超时 sentinel parallel-syncs mymaster 1 # 同时同步的从库数

Cluster — 哈希槽与重定向

# 哈希槽分配 # 总共 16384 个槽 # CRC16(key) % 16384 → 确定槽 → 确定节点 # 分配示例(3 主 3 从) # 节点 A: 槽 0-5460 # 节点 B: 槽 5461-10922 # 节点 C: 槽 10923-16383 # MOVED 重定向(槽已迁移) GET user:1001 # → MOVED 3999 192.168.1.101:6379 # 客户端收到 MOVED 后更新槽映射,重新请求 # ASK 重定向(槽迁移中) GET user:1001 # → ASK 3999 192.168.1.101:6379 # 客户端发送 ASKING 命令后重新请求 # ASK 是临时重定向,不更新槽映射
中级要点:主从全量同步用 RDB + buffer;Sentinel 通过 Raft 选 Leader 执行故障转移;Cluster 用哈希槽分片。

高级拓展

Gossip 协议 — Cluster 节点通信

Cluster 节点间通过 Gossip 协议交换信息,包括节点状态、槽分配等。每个节点随机选择几个节点发送 PING,收到 PONG 回复。

# Gossip 消息类型 # MEET: 邀请新节点加入集群 # PING: 心跳检测 + 交换信息 # PONG: 回复 PING/MEET # FAIL: 广播节点下线 # PUBLISH: 发布订阅消息 # 为什么是 16384 个槽? # 1. 心跳包中包含槽信息(bitmap),16384 位 = 2KB # 2. 65536 个槽 → 8KB 心跳包太大 # 3. 节点数通常不超过 1000,16384 足够均匀分配

Cluster 限制

# Cluster 不支持的操作 # 1. 多 key 操作(除非 key 在同一槽) # 解决:用 {} 指定 hash tag # MSET {user:1}.name "张三" {user:1}.age 18 # # {} 内的部分用于计算哈希槽 # 2. 事务(MULTI/EXEC)跨节点不支持 # 3. Lua 脚本中涉及的 key 必须在同一节点 # 4. 批量操作需要客户端实现(如 pipeline 按节点分组)

实战场景

场景:Cluster 扩容

# 1. 启动新节点 redis-server --port 6380 --cluster-enabled yes # 2. 加入集群 redis-cli --cluster add-node 192.168.1.104:6380 192.168.1.101:6379 # 3. 重新分配槽 redis-cli --cluster reshard 192.168.1.101:6379 # 输入要迁移的槽数、目标节点 ID、源节点 ID # 4. 添加从节点 redis-cli --cluster add-node 192.168.1.105:6380 192.168.1.101:6379 \ --cluster-slave --cluster-master-id <master-id> # 5. 验证 redis-cli --cluster check 192.168.1.101:6379

面试模拟

面试官:Redis Cluster 的数据分片原理?

你:使用 16384 个哈希槽,CRC16(key) % 16384 确定槽,每个节点负责一部分槽。客户端访问错误节点时返回 MOVED 重定向(槽已迁移)或 ASK 重定向(槽迁移中)。节点间通过 Gossip 协议交换槽映射信息。

面试官:Sentinel 怎么判断主库下线?

你:分两步:1)主观下线(SDOWN):单个 Sentinel 在 down-after-milliseconds 时间内收不到主库响应,认为主库主观下线;2)客观下线(ODOWN):quorum 个 Sentinel 都认为主库主观下线,则判定为客观下线。客观下线后 Sentinel 之间通过 Raft 选举 Leader 执行故障转移。