5月28日 09:35

Redis 主从复制、哨兵和集群模式有什么区别?高可用方案怎么选?

Redis 的主从复制、哨兵模式和集群模式是三种不同层次的高可用方案,它们解决的核心问题不同,选择时需要根据业务的数据规模、可用性要求和读写瓶颈来决定。

主从复制:解决读瓶颈和数据备份

主从复制是最基础的方案。一个 Redis 节点作为 Master 负责写操作,一个或多个 Slave 节点从 Master 同步数据,只提供读服务。

同步过程分两个阶段:首次连接时 Master 执行 BGSAVE 生成 RDB 快照发送给 Slave(全量同步);之后的写命令通过 repl-backlog 缓冲区持续发送给 Slave(增量同步)。如果 Slave 断开时间过长,缓冲区被覆盖,就会再次触发全量同步。

bash
slaveof 192.168.1.100 6379

主从复制的核心价值是读写分离——把读流量分散到多个 Slave 上,同时 Slave 作为数据副本提供冗余。但它的致命问题是 Master 挂了之后需要人工介入,把某个 Slave 手动提升为 Master,还要修改应用配置指向新地址,恢复时间完全取决于运维响应速度。

适用场景:数据量不大、读多写少、能容忍短暂不可用的内部系统。比如配置中心、排行榜这类读远多于写的业务。

哨兵模式:在主从基础上实现自动故障转移

哨兵模式本质是主从复制 + 自动化运维。部署一组 Sentinel 进程(至少3个,奇数个),它们持续监控 Master 和 Slave 的状态,Master 故障时自动完成故障转移。

故障转移的核心机制:主观下线与客观下线

单个 Sentinel 检测到 Master 无响应(超过 down-after-milliseconds),标记为主观下线(SDOWN)。但这可能只是网络抖动,所以需要多个 Sentinel 互相确认——当超过 quorum 个数的 Sentinel 都认为 Master 下线时,才标记为客观下线(ODOWN),此时才会触发真正的故障转移。

故障转移流程

  1. Sentinel 集群通过 Raft 协议选出一个 Leader Sentinel 执行转移
  2. Leader 从 Slave 中选出新 Master(优先判断复制偏移量最大、连接最稳定的节点)
  3. 对新 Master 执行 SLAVEOF NO ONE,将其提升为主节点
  4. 通知其他 Slave 复制新 Master
  5. 更新 Sentinel 的监控配置
bash
port 26379 sentinel monitor mymaster 192.168.1.100 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 180000

配置中 2 表示至少需要 2 个 Sentinel 同意才能判定客观下线。生产环境建议至少部署 3 个 Sentinel,跨机房分布,避免 Sentinel 自身成为单点。

客户端需要使用 Sentinel 模式连接——先从 Sentinel 获取当前 Master 地址,再连接 Master。当故障转移完成后,Sentinel 会通知客户端切换到新 Master。

局限性

哨兵解决了自动故障转移,但写操作仍然只能走 Master 单点,存储容量也受限于单机内存。当数据量超过单机内存,或者写 QPS 成为瓶颈时,哨兵模式就不够用了。

适用场景:数据量在单机内存范围内,但需要高可用、要求故障自动恢复的业务。大部分中小规模的生产环境用哨兵模式就足够了。

集群模式:解决写瓶颈和存储瓶颈

Redis Cluster 是真正的分布式方案,通过数据分片把数据分散到多个 Master 节点上,每个 Master 持有部分数据,同时可以有自己的 Slave 做副本。

哈希槽分片机制

Cluster 把整个键空间划分为 16384 个哈希槽,每个 Master 负责一部分槽。客户端写入一个 key 时,用 CRC16(key) % 16384 计算出槽编号,然后路由到负责该槽的节点。

当集群需要扩容时,只需把一部分哈希槽从旧节点迁移到新节点,不需要停服。收缩时反向操作。

请求重定向:MOVED 和 ASK

客户端向错误节点发送请求时,该节点会返回重定向指令:

  • MOVED:表示该槽已经永久迁移到新节点,客户端应更新本地缓存
  • ASK:表示该槽正在迁移中(临时状态),客户端本次请求转发到目标节点,但不更新缓存
bash
cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000

创建集群:

bash
redis-cli --cluster create \ 192.168.1.1:7000 192.168.1.2:7001 192.168.1.3:7002 \ 192.168.1.4:7003 192.168.1.5:7004 192.168.1.6:7005 \ --cluster-replicas 1

节点通信与故障检测

Cluster 采用 Gossip 协议进行节点间通信,每个节点定期向其他节点发送 PING 消息交换集群状态。当某个 Master 被超过半数 Master 标记为故障(PFAIL → FAIL),其 Slave 会自动提升为新 Master。

限制

  • 不支持跨槽的多键操作(MGETMSET 等操作的 key 必须在同一槽,可用 hash tag {tag} 解决)
  • 不支持跨槽的 WATCH 事务
  • KEYSSCAN 等命令只能看到当前节点的数据
  • 最少需要 6 个节点(3 主 3 从)才能保证高可用

适用场景:数据量超过单机内存、写 QPS 单机无法承载、需要在线扩缩容的大规模业务。

三种方案的核心区别

特性主从复制哨兵模式集群模式
故障转移手动自动(Sentinel 选举)自动(Gossip + 投票)
写扩展不支持不支持支持(数据分片)
存储扩展受限于单机受限于单机支持(水平扩容)
最小部署2 节点2 Redis + 3 Sentinel6 节点(3主3从)
运维复杂度
客户端要求普通支持 Sentinel 协议支持 Cluster 协议

面试中如何回答

面试官问这个问题,核心考察的是你对 Redis 高可用演进路径的理解,而不只是背诵概念。建议从问题驱动的角度组织回答:

第一步,先说清楚每种方案解决什么问题——主从解决读瓶颈,哨兵解决自动故障转移,集群解决写瓶颈和存储瓶颈。这三个是递进关系,不是并列选择。

第二步,结合实际场景给出选型依据:数据量小 + 可容忍短时不可用 → 主从;数据量小 + 要求高可用 → 哨兵;数据量大或写 QPS 高 → 集群。

第三步,补充生产经验。比如哨兵部署要跨机架、集群扩容时注意槽迁移对大 key 的影响、客户端重试策略要处理 MOVED/ASK 重定向等。这些细节能体现你的实战深度。

标签:Redis