谈谈 Redis 集群模式?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

面试官提出这个问题,通常旨在考察以下几个维度:

  1. 对分布式缓存架构的理解深度:面试官不仅想知道你知道几种集群模式,更想了解你是否理解每种模式所解决的的核心问题(如高可用、水平扩展、数据一致性等)。
  2. 技术选型与权衡能力:你是否能清晰地对比不同模式的优缺点,并说明各自的适用场景,这能反映你在实际项目中做技术决策的能力。
  3. 对分布式系统核心原理的掌握:问题背后可能涉及到数据分片策略(如哈希槽)、故障转移机制(如哨兵选举)、数据一致性(如主从异步复制)等分布式基础概念。
  4. 实践经验:是否有在真实生产环境中部署、使用或排错 Redis 集群的经验,能否说出一些最佳实践和常见坑点

核心答案

Redis 主要的集群模式有三种,分别解决不同规模场景下的问题:

  1. 主从复制(Replication):最基本模式,一主多从。主节点负责写,从节点同步主节点数据并负责读,实现了读写分离数据备份。但故障时需要手动干预,不具备自动故障转移能力。
  2. 哨兵模式(Sentinel):在主从复制基础上,引入了哨兵进程来监控所有节点。当主节点故障时,哨兵能自动完成故障发现和转移,并通知客户端新的主节点地址,实现了高可用(HA)。但它未解决数据水平分片(即存储容量受限) 的问题。
  3. 集群模式(Cluster,官方方案):Redis 3.0 后提供的分布式数据分片方案。它采用去中心化架构,将数据按哈希槽(slot,共16384个)分片存储在不同主节点上,支持水平扩展。每个主节点都有对应的从节点,实现了高可用负载均衡。这是应对海量数据和高并发场景的终极方案

深度解析

原理/机制

  • 主从复制:核心是 PSYNC 命令。从节点首次连接进行全量同步(RDB文件),之后通过命令传播进行增量同步。但它是异步复制,存在数据延迟甚至极小概率的数据丢失风险。
  • 哨兵模式:哨兵通过定期 PING 节点判断其存活状态。判定主节点“宕机”需经过主观下线客观下线(多个哨兵达成共识)的过程。故障转移时,会基于 Raft 算法变种选举出领头哨兵,由它完成从节点晋升和新主节点切换。
  • 集群模式
    • 数据分片:采用 CRC16(key) mod 16384 计算 key 所属的哈希槽。每个节点负责一部分槽位。这种设计使得增删节点时,仅需移动部分槽位的数据,而非重新哈希所有 key。
    • 节点通信:节点间通过 Gossip 协议交换信息,维护集群元数据。客户端可直连任意节点,如果请求的 key 不在该节点,节点会返回 MOVED 重定向错误,指引客户端连接正确节点。

代码示例(以 Jedis/Lettuce 连接 Cluster 为例):

// 使用 Lettuce 客户端连接 Redis Cluster
Set<RedisURI> nodes = new HashSet<>();
nodes.add(RedisURI.create(“redis://node1:6379”));
nodes.add(RedisURI.create(“redis://node2:6379”));
nodes.add(RedisURI.create(“redis://node3:6379”));

RedisClusterClient clusterClient = RedisClusterClient.create(nodes);
StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
RedisAdvancedClusterCommands<String, String> commands = connection.sync();

// 客户端内部会处理 MOVED/ASK 重定向
commands.set(“user:1001”, “Alice”);
String value = commands.get(“user:1001”);

对比分析与最佳实践

特性主从复制哨兵模式集群模式 (Cluster)
核心目标数据冗余、读写分离高可用 (HA)高可用 + 水平扩展
数据分片
写能力扩展否(单主)否(单主)是(多主)
故障转移手动自动自动
复杂度
适用场景数据备份、读多写少读多写少,且对可用性要求高海量数据、高并发读写
  • 最佳实践
    1. 生产环境禁用 keys * 命令,尤其在 Cluster 中,它只返回当前节点的 key。
    2. 使用 Cluster 时,避免产生大 key,防止数据倾斜和迁移阻塞。
    3. 涉及多个 key 的操作(如 mgetmset),需确保所有 key 位于同一个哈希槽(可使用 {hash_tag} 强制指定,如 user:{1001}:profileuser:{1001}:order)。
    4. 合理配置哨兵或集群的超时参数,防止网络抖动导致的误切换。

常见误区

  1. 认为主从复制能自动故障转移:不能,它只负责数据同步。
  2. 认为哨兵模式是分布式:不是,它解决的是高可用,主节点仍是单点写入,容量和写性能有上限。
  3. 认为 Redis Cluster 支持强一致性:不支持。它采用异步复制,故障转移时可能丢失写入(尽管时间窗口极短)。对强一致性有要求,需配合 WAIT 命令或使用其他方案。

总结

简单来说,主从复制是基础,哨兵模式解决了它的高可用问题,而集群模式最终通过数据分片解决了大规模数据存储和写入扩展的瓶颈。选择哪种模式,完全取决于你的数据量、并发量和可用性要求。