Redis Cluster 集群模式深度拆解
一、为什么我们必须用 Redis Cluster?
1. 单机与哨兵模式的致命短板
先明确三个架构的能力边界,避免架构选型错误:
表格
| 架构 | 数据存储 | 写入能力 | 高可用 | 适用场景 |
|---|---|---|---|---|
| 单机 | 单节点全量数据 | 单主写入上限~5 万 QPS | 无 | 开发测试、小数据量业务 |
| 哨兵模式 | 主从全量复制 | 单主写入上限~5 万 QPS | 自动故障转移 | 数据量 < 10GB、写入压力不大的业务 |
| Cluster 集群 | 数据分片存储 | 多主并行写入,线性扩展 | 自动故障转移 | 数据量 > 10GB、高并发写入、需要水平扩展的业务 |
哨兵模式的核心痛点:
- 所有数据都在主节点上,单节点内存不能太大(建议不超过 16GB),否则 RDB/AOF 持久化、主从同步会严重影响性能
- 只有一个主节点负责写入,写入能力无法水平扩展
- 热点 Key 会集中在单个主节点,导致该节点 CPU / 内存飙升,成为系统瓶颈
2. Redis Cluster 的核心价值
Redis Cluster 是官方在 Redis 3.0 推出的原生分布式方案,解决了哨兵模式的所有痛点:
- 数据分片存储:将所有数据分散到多个主节点上,每个主节点只负责一部分数据,突破单节点内存限制
- 写入能力线性扩展:多个主节点并行处理写入请求,集群整体写入能力随节点数量线性增长
- 高可用自动运维:每个主节点都有对应的从节点,主节点宕机后自动选举新主,无需人工干预
- 去中心化架构:所有节点对等,没有中心节点,任意节点宕机不影响集群整体可用性
- 自动数据迁移:支持在线扩容缩容,数据自动在节点间迁移,业务无感知
二、Redis Cluster 核心架构与原理
2.1 标准集群架构:3 主 3 从
生产环境标准架构是3 主 3 从,这是最小的高可用集群配置:
- 3 个主节点(Master):负责数据存储和读写请求
- 3 个从节点(Slave):每个主节点对应一个从节点,同步主节点数据,主节点宕机时升级为新主
- 所有节点两两之间通过 Gossip 协议通信,交换集群元数据
plaintext
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Master1 │ │ Master2 │ │ Master3 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ Slave1 │ │ Slave2 │ │ Slave3 │
└─────────┘ └─────────┘ └─────────┘
关键:主节点数量必须是奇数,避免脑裂;每个主节点至少有一个从节点,保证高可用。
2.2 核心原理:哈希槽(Hash Slot)分片机制
Redis Cluster 没有使用一致性哈希,而是采用了 ** 哈希槽(Hash Slot)** 的分片方式,这是它最核心的设计。
整个集群被划分为16384 个哈希槽(0-16383),每个主节点负责一部分哈希槽。当客户端写入一个 Key 时,Redis 会对 Key 进行 CRC16 哈希计算,然后对 16384 取模,得到该 Key 对应的哈希槽,再将数据写入负责该哈希槽的主节点。
计算公式:
plaintext
slot = CRC16(key) % 16384
例如:
- Key "user:1" 计算得到 slot=100,写入负责 slot 100 的主节点
- Key "order:123" 计算得到 slot=5000,写入负责 slot 5000 的主节点
哈希槽相比一致性哈希的优势:
- 数据分布更均匀,不会出现一致性哈希的热点问题
- 扩容缩容更简单,只需要迁移对应的哈希槽即可
- 元数据量小,16384 个槽的信息只需要 2KB 就能存储
2.3 节点通信:Gossip 协议
Redis Cluster 是去中心化架构,没有中心节点存储集群元数据,所有节点通过Gossip 协议(流言协议)两两通信,交换集群状态信息。
每个节点每秒都会随机向其他几个节点发送 PING 消息,收到 PING 的节点会回复 PONG 消息。通过这种方式,所有节点最终都会获得整个集群的完整元数据,包括:
- 所有节点的地址、端口、角色(主 / 从)
- 每个主节点负责的哈希槽范围
- 节点的健康状态
2.4 客户端路由:重定向机制
客户端可以连接集群中的任意一个节点发送请求。如果请求的 Key 所在的哈希槽正好由该节点负责,节点会直接处理请求;如果不是,节点会返回一个MOVED 重定向响应,告诉客户端该 Key 所在的正确节点地址,客户端再向正确的节点重新发送请求。
现代 Redis 客户端(如 Lettuce、JedisCluster)已经封装了重定向逻辑,会自动缓存哈希槽与节点的映射关系,大部分情况下不需要客户端手动处理重定向。
三、Redis Cluster 故障转移全流程
和哨兵模式类似,Redis Cluster 也有完整的自动故障转移机制,但实现原理完全不同。
3.1 节点下线判定
- 主观下线(PFail):当一个节点 A 向节点 B 发送 PING 消息,超过指定时间没有收到 PONG 响应,节点 A 会将节点 B 标记为主观下线。
- 客观下线(Fail):当集群中有超过半数的主节点都将节点 B 标记为主观下线时,节点 B 会被标记为客观下线,触发故障转移。
注意:只有主节点参与投票,从节点不参与下线判定投票。
3.2 从节点选举
当一个主节点被标记为客观下线后,它的所有从节点会开始竞选新主:
- 从节点向集群中所有其他主节点发送竞选请求
- 每个主节点只能给一个从节点投票,先到先得
- 获得超过半数主节点投票的从节点,升级为新的主节点
- 新主节点接管原主节点负责的所有哈希槽
- 集群广播新的主从关系,更新所有节点的元数据
3.3 旧主节点恢复
旧主节点修复重启后,会自动降级为新主节点的从节点,同步新主节点的数据,重新加入集群。
四、生产环境 Redis Cluster 标准部署
以 Redis 7.0 版本为例,部署 3 主 3 从集群,服务器规划:
表格
| 服务器 IP | 主节点端口 | 从节点端口 |
|---|---|---|
| 192.168.1.10 | 6379 | 6380 |
| 192.168.1.11 | 6379 | 6380 |
| 192.168.1.12 | 6379 | 6380 |
第一步:安装 Redis
在所有 3 台服务器上执行相同操作:
bash
运行
# 下载Redis
wget https://download.redis.io/releases/redis-7.0.12.tar.gz
tar -zxvf redis-7.0.12.tar.gz
cd redis-7.0.12
make && make install
# 创建目录
mkdir -p /usr/local/redis/{conf,data,log}
第二步:配置主节点
在每台服务器上创建主节点配置文件/usr/local/redis/conf/redis-6379.conf:
conf
# 基础配置
port 6379
bind 0.0.0.0
daemonize yes
pidfile /var/run/redis-6379.pid
logfile /usr/local/redis/log/redis-6379.log
dir /usr/local/redis/data/6379
# 集群配置
cluster-enabled yes # 开启集群模式
cluster-config-file nodes-6379.conf # 集群节点配置文件
cluster-node-timeout 15000 # 节点超时时间,毫秒
cluster-require-full-coverage no # 允许部分哈希槽不可用时集群继续提供服务
# 持久化配置
appendonly yes
appendfilename "appendonly-6379.aof"
save 900 1
save 300 10
save 60 10000
# 安全配置
requirepass 123456
masterauth 123456
第三步:配置从节点
在每台服务器上创建从节点配置文件/usr/local/redis/conf/redis-6380.conf,只需要修改端口和文件名称:
conf
port 6380
pidfile /var/run/redis-6380.pid
logfile /usr/local/redis/log/redis-6380.log
dir /usr/local/redis/data/6380
cluster-config-file nodes-6380.conf
appendfilename "appendonly-6380.aof"
# 其余配置和主节点完全一致
第四步:启动所有节点
在所有 3 台服务器上启动主节点和从节点:
bash
运行
# 启动主节点
redis-server /usr/local/redis/conf/redis-6379.conf
# 启动从节点
redis-server /usr/local/redis/conf/redis-6380.conf
第五步:创建集群
使用 Redis 自带的redis-cli工具创建集群:
bash
运行
redis-cli --cluster create \
192.168.1.10:6379 192.168.1.11:6379 192.168.1.12:6379 \
192.168.1.10:6380 192.168.1.11:6380 192.168.1.12:6380 \
--cluster-replicas 1 \
-a 123456
参数说明:
--cluster create:创建集群- 前 3 个地址是主节点,后 3 个是从节点
--cluster-replicas 1:每个主节点对应 1 个从节点-a 123456:Redis 密码
执行命令后,工具会自动分配哈希槽和主从关系,输入yes确认即可完成集群创建。
第六步:验证集群状态
bash
运行
# 连接任意节点
redis-cli -c -h 192.168.1.10 -p 6379 -a 123456
# 查看集群状态
cluster info
# 查看节点列表
cluster nodes
如果输出显示cluster_state:ok,说明集群创建成功。
五、Spring Boot 整合 Redis Cluster
整合非常简单,只需要修改配置文件即可,代码不需要任何改动。
第一步:引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
第二步:配置集群连接
spring:
redis:
password: 123456
cluster:
nodes:
- 192.168.1.10:6379
- 192.168.1.11:6379
- 192.168.1.12:6379
- 192.168.1.10:6380
- 192.168.1.11:6380
- 192.168.1.12:6380
lettuce:
pool:
max-active: 200
max-wait: -1
max-idle: 20
min-idle: 5
第三步:使用 RedisTemplate
和单机 Redis 完全一样,直接注入 RedisTemplate 使用即可:
java
运行
@Service
public class UserService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public User getUserById(Long id) {
String key = "user:" + id;
return (User) redisTemplate.opsForValue().get(key);
}
public void saveUser(User user) {
String key = "user:" + user.getId();
redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS);
}
}
六、生产环境高频坑点与解决方案
坑 1:数据倾斜问题
问题描述:部分主节点的数据量和访问量远大于其他节点,导致这些节点负载过高,成为集群瓶颈。
产生原因:
- Key 分布不均匀,大量 Key 集中在少数哈希槽
- 大 Key 问题,单个 Key 占用几十 MB 甚至几百 MB 内存
- 哈希槽分配不合理
解决方案:
- 合理设计 Key,避免相同前缀的 Key 过多
- 拆分大 Key,将大 Hash、大 List 拆分成多个小 Key
- 重新分配哈希槽,将负载高的节点的部分哈希槽迁移到负载低的节点
坑 2:热点 Key 问题
问题描述:某个 Key 的访问量极高,导致负责该 Key 的主节点 CPU 使用率 100%,服务卡死。
解决方案:
- 热点 Key 本地缓存:在应用层加一层本地缓存(如 Caffeine),减少 Redis 访问量
- 热点 Key 复制:将热点 Key 复制多份,分布到不同的主节点上
- 读写分离:热点 Key 的读请求路由到从节点
坑 3:大 Key 问题
问题描述:单个 Key 的 value 过大,导致读写超时、网络阻塞、内存溢出。
危害:
- 读取大 Key 会占用大量网络带宽,导致其他请求超时
- 大 Key 的删除会阻塞 Redis 主线程,导致整个集群卡顿
- 主从同步大 Key 会导致从节点同步延迟
解决方案:
- 拆分大 Key:将大 Hash 拆分为多个小 Hash,大 List 拆分为多个小 List
- 压缩 value:对大 value 进行压缩后再存储
- 避免使用 Redis 存储大文件,大文件应该存储在对象存储(如 OSS)中
坑 4:集群脑裂问题
问题描述:网络分区导致集群分裂成两个独立的子集群,两个子集群都认为自己是正常的,同时处理写入请求,导致数据不一致。
解决方案:
- 主节点数量必须是奇数
- 合理设置
cluster-node-timeout参数,不要设置过小 - 开启
cluster-require-full-coverage no,避免部分哈希槽不可用时整个集群不可用
坑 5:扩容缩容失败
问题描述:在线扩容缩容时,数据迁移失败,导致部分哈希槽不可用。
解决方案:
- 扩容缩容前备份所有数据
- 选择业务低峰期进行操作
- 迁移过程中监控集群状态,避免迁移速度过快影响业务
- 迁移完成后验证数据完整性
七、生产环境最佳实践
-
集群规模规划:
- 单个主节点内存不要超过 16GB,建议 8-16GB
- 主节点数量不要超过 10 个,否则 Gossip 协议通信开销会很大
- 每个主节点至少配置 1 个从节点,核心业务配置 2 个从节点
-
硬件配置:
- 使用 SSD 磁盘,提升持久化和主从同步性能
- 内存大小至少是数据量的 2 倍,预留足够的内存给系统和 Redis
- CPU 核心数不少于 4 核,Redis 是单线程,但集群模式下多个节点会占用多个核心
-
配置优化:
- 开启 AOF 持久化,使用
appendfsync everysec策略 - 合理设置
cluster-node-timeout为 15000-30000 毫秒 - 关闭
cluster-require-full-coverage,提高集群可用性 - 开启内存淘汰策略,使用
allkeys-lru
- 开启 AOF 持久化,使用
-
运维监控:
- 监控集群状态、节点健康状态、哈希槽分布
- 监控每个节点的内存使用率、CPU 使用率、网络流量
- 监控大 Key、热点 Key,及时发现和处理
- 配置告警规则,当节点下线、内存使用率过高、响应时间过长时及时告警
-
数据备份:
- 定期备份 RDB 文件,至少每天备份一次
- 备份文件存储在不同的服务器上,避免单点故障
- 定期测试数据恢复流程,确保备份可用
总结
Redis Cluster 是处理海量数据和高并发写入的标准解决方案,也是中高级后端工程师必须掌握的核心技能。它通过哈希槽分片实现了数据的分布式存储,通过 Gossip 协议实现了去中心化的节点通信,通过自动故障转移实现了高可用。
- 当数据量超过 10GB 或写入 QPS 超过 1 万时,必须使用 Redis Cluster
- 核心原理是 16384 个哈希槽的分片机制,每个主节点负责一部分哈希槽
- 故障转移流程:主观下线→客观下线→从节点选举→新主接管
- 生产标准架构是 3 主 3 从,跨机器部署,杜绝单点故障
- 生产环境最常见的坑是数据倾斜、热点 Key、大 Key 和脑裂
- 遵循最佳实践,合理规划集群规模、优化配置、加强监控,才能保证集群稳定运行
更多推荐




所有评论(0)