4. 分布式缓存架构:Redis作为分布式缓存、Redis集群模式(主从/哨兵/Cluster)、缓存分片与一致性哈希

在单机缓存无法满足高并发与高可用场景时,分布式缓存成为必然选择。Redis 作为业界最主流的分布式缓存组件,提供了从主从复制到无中心化集群的完整演进路径。本节将深入剖析 Redis 的三种集群架构、缓存分片策略以及一致性哈希的核心原理,帮助你在 Spring Boot 项目中做出正确的架构选型。

4.1 Redis 作为分布式缓存的核心价值

Redis 之所以能成为分布式缓存的事实标准,主要得益于以下特性:

特性 说明 对缓存一致性的影响
纯内存操作 数据全部存储在内存中,读写延迟通常在微秒级 快速响应减少数据不一致窗口
丰富的数据结构 支持 String、Hash、List、Set、Sorted Set 等 Hash 结构便于原子化更新部分字段
发布/订阅 支持消息通知机制 可用于缓存失效广播
Lua 脚本 服务端原子执行多条命令 实现 CAS(Check-And-Set)操作
持久化 RDB 快照 + AOF 日志 重启后快速恢复缓存数据
架构决策要点: 在 Spring Boot 项目中,Redis 通常通过 spring-boot-starter-data-redis 集成。选择哪种集群模式,直接决定了缓存一致性的实现复杂度与运维成本。

4.2 Redis 集群模式演进:主从 → 哨兵 → Cluster

Redis 的集群架构经历了三个重要阶段,每一阶段解决了上一阶段的痛点,同时也引入了新的权衡。

4.2.1 主从复制模式

主从模式是 Redis 高可用的基础。一个主节点(Master)负责写操作,多个从节点(Slave)负责读操作,数据通过异步复制同步到从节点。

Redis 主从复制架构 Master(主节点) 读写:写请求 Slave-1(从节点) 只读:分担读流量 Slave-2(从节点) 只读:分担读流量 Slave-3(从节点) 只读:分担读流量 Spring Boot 应用 ⚠ 异步复制:主从数据存在短暂延迟
适用场景: 读多写少、允许秒级数据不一致的业务。例如:商品详情页缓存、配置信息缓存。

主从模式的关键问题:

  • 写瓶颈: 所有写操作集中在 Master,单点写入能力有限。
  • 故障转移需手动: Master 宕机后,需要人工将从节点提升为主节点。
  • 数据不一致: 异步复制导致从节点数据滞后,读取到过期数据。

4.2.2 哨兵模式

哨兵模式在主从基础上增加了自动故障转移能力。哨兵(Sentinel)是一个独立进程,负责监控 Master 和 Slave 的健康状态,并在 Master 宕机时自动选举新 Master。

哨兵功能 工作机制 对缓存一致性的影响
监控 每秒向所有节点发送 PING 命令 快速感知节点故障
自动故障转移 选举新 Master,更新客户端配置 切换期间缓存不可用,可能丢失未同步数据
配置提供 客户端通过哨兵获取当前 Master 地址 保证客户端始终连接可用节点
通知 通过发布/订阅通知客户端状态变化 支持客户端主动刷新连接
缓存一致性风险: 哨兵模式下,故障转移发生时,如果旧 Master 的数据尚未完全同步到新 Master,这部分数据将永久丢失。对于要求强一致性的缓存场景,需要结合业务补偿机制。

4.2.3 Cluster 集群模式

Redis Cluster 是官方提供的分布式解决方案,实现了数据自动分片(Sharding)和高可用。它去中心化,每个节点都保存集群元数据,客户端可以直连任意节点。

Redis Cluster 无中心化架构 Node-1 (Master) Slot: 0-5460 Slave: Node-4 Node-4 (Slave) Node-2 (Master) Slot: 5461-10922 Slave: Node-5 Node-5 (Slave) Node-3 (Master) Slot: 10923-16383 Slave: Node-6 Node-6 (Slave) Spring Boot 客户端 Cluster 核心机制 • 16384 个哈希槽(Hash Slot)均匀分布到所有 Master 节点 • 客户端直连任意节点,通过 MOVED/ASK 重定向找到正确节点 • 节点间通过 Gossip 协议交换元数据,去中心化无单点瓶颈
Cluster 模式优势:
  • 线性扩展: 增加节点即可线性提升吞吐量和存储容量。
  • 自动故障转移: Master 宕机后,其 Slave 自动晋升为 Master。
  • 无中心化: 每个节点都持有完整路由信息,不存在单点瓶颈。

4.3 缓存分片策略

缓存分片(Sharding)是将数据分散到多个 Redis 实例上的技术。分片策略直接决定了数据分布的均匀性、扩展的灵活性以及查询的效率。

4.3.1 三种主流分片策略对比

分片策略 实现方式 优点 缺点 适用场景
客户端分片 应用层通过哈希算法决定 key 写入哪个节点 实现简单,无额外组件 节点变更需修改客户端逻辑 中小规模、节点固定
代理分片 通过 Twemproxy、Codis 等代理层路由 客户端无感知,统一管理 代理层成为性能瓶颈和单点 需要统一运维管控
Redis Cluster 官方内置哈希槽分片 去中心化,自动重分片 客户端需支持 Cluster 协议 大规模、高可用要求高

4.3.2 哈希槽分片原理(Redis Cluster)

Redis Cluster 采用固定 16384 个哈希槽(Hash Slot)的分片方案。每个 key 通过 CRC16 算法计算哈希值,然后对 16384 取模,得到对应的槽位。每个 Master 节点负责一段连续的槽位区间。

// 哈希槽计算公式
slot = CRC16(key) % 16384

// 示例:3 个 Master 节点的槽位分配
// Node-1: 0 ~ 5460
// Node-2: 5461 ~ 10922
// Node-3: 10923 ~ 16383
为什么是 16384 个槽? 16384 = 2^14,CRC16 输出 16 位,取模 16384 可保证均匀分布。同时,16384 个槽的元数据仅占用约 2KB 内存,适合在节点间通过 Gossip 协议高频传播。

4.4 一致性哈希:解决节点变更时的缓存雪崩

传统取模分片(hash(key) % N)在节点数量变化时,会导致大量 key 的映射关系改变,引发缓存雪崩——大量请求同时穿透到数据库。一致性哈希(Consistent Hashing)正是为解决这一问题而生。

4.4.1 一致性哈希核心原理

一致性哈希将整个哈希值空间组织成一个虚拟的圆环(Hash Ring),范围通常为 0 ~ 2^32-1。每个节点根据其 IP 或名称计算哈希值,放置在圆环上。每个 key 也计算哈希值,沿圆环顺时针找到第一个节点,即为该 key 的存储节点。

一致性哈希环(Consistent Hash Ring) A Node-A B Node-B C Node-C Key-1 Key-2 Key-3 查找规则 Key 沿圆环顺时针查找 遇到的第一个节点即为目标

4.4.2 虚拟节点:解决数据倾斜

实际部署中,物理节点在哈希环上的分布可能不均匀,导致某些节点负载过高(数据倾斜)。虚拟节点(Virtual Node)技术为每个物理节点创建多个虚拟副本,均匀分布在环上,使数据分布更加均衡。

// 虚拟节点实现思路(伪代码)
public class ConsistentHash<T> {
    private final HashFunction hashFunction;
    private final int numberOfReplicas;  // 每个物理节点的虚拟节点数
    private final SortedMap<Integer, T> circle = new TreeMap<>();

    public void addNode(T node) {
        for (int i = 0; i < numberOfReplicas; i++) {
            circle.put(hashFunction.hash(node.toString() + i), node);
        }
    }

    public T getNode(Object key) {
        if (circle.isEmpty()) return null;
        int hash = hashFunction.hash(key);
        // 找到第一个大于等于 hash 的虚拟节点
        SortedMap<Integer, T> tailMap = circle.tailMap(hash);
        Integer nodeHash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
        return circle.get(nodeHash);
    }
}
一致性哈希的优势量化:
  • 节点增加: 只有约 1/N 的 key 需要重新映射(N 为节点总数)。
  • 节点减少: 只有该节点上的 key 需要迁移到其他节点。
  • 对比传统取模: 节点从 3 台扩展到 4 台时,传统取模导致 75% 的 key 迁移;一致性哈希仅迁移约 25%。

4.5 架构选型决策矩阵

在 Spring Boot 项目中,选择哪种 Redis 集群模式需要综合考虑业务规模、一致性要求、运维能力等因素。以下决策矩阵可供参考:

评估维度 主从模式 哨兵模式 Cluster 模式
数据量 单机内存上限(通常 < 64GB) 单机内存上限 可扩展至 PB 级(通过增加节点)
QPS 读:随从节点线性扩展;写:单点瓶颈 读:随从节点线性扩展;写:单点瓶颈 读写均随节点数线性扩展
高可用 需手动故障转移 自动故障转移(30s 内) 自动故障转移(秒级)
数据一致性 弱一致性(异步复制) 弱一致性(故障转移可能丢数据) 弱一致性(异步复制,支持 WAIT 命令)
运维复杂度 低 中(需部署哨兵集群) 高(需规划槽位、处理 resharding)
客户端支持 Lettuce/Jedis 原生支持 Lettuce/Jedis 原生支持 需使用 Cluster 模式客户端
Spring Boot 集成 spring.redis.host spring.redis.sentinel.master spring.redis.cluster.nodes
重要提醒: 无论选择哪种集群模式,Redis 本身不提供强一致性保证。在缓存一致性要求极高的场景(如库存扣减、金融交易),必须结合分布式锁、版本号或业务层补偿机制来保证最终一致性。切勿将 Redis 当作关系型数据库使用。

4.6 本章小结

分布式缓存架构的核心在于平衡性能、可用性与一致性。Redis 从主从复制到 Cluster 集群的演进,体现了分布式系统设计的经典权衡:

  • 主从模式 适合读多写少、允许短暂不一致的小规模场景。
  • 哨兵模式 在主从基础上实现了自动故障转移,适合对可用性有要求的中型业务。
  • Cluster 模式 通过哈希槽分片和去中心化架构,支撑大规模、高并发的缓存需求。
  • 一致性哈希 作为分片算法的基石,有效降低了节点变更时的缓存迁移成本。