4. Redis Cluster 集群模式:数据分片、哈希槽、节点通信、集群伸缩
Redis Cluster 是 Redis 官方提供的分布式解决方案,旨在解决单机内存容量有限、单点故障以及高并发写入瓶颈等问题。它通过数据分片实现水平扩展,通过哈希槽进行数据路由,通过节点间通信维护集群状态,并支持在线伸缩。本节将深入剖析这四大核心机制。
4.1 数据分片与哈希槽
Redis Cluster 采用无中心化架构,数据被自动划分为 16384 个哈希槽(Hash Slot)。每个键通过 CRC16 算法计算后对 16384 取模,决定其所属的槽位。集群中的每个主节点负责管理一部分哈希槽。
核心公式:
slot = CRC16(key) % 16384
这种设计使得数据分布均匀,且节点增减时只需迁移槽位,无需全量重哈希。
哈希槽分配示例
| 节点 | 负责的哈希槽范围 | 槽位数量 |
|---|---|---|
| Node A (Master) | 0 – 5460 | 5461 |
| Node B (Master) | 5461 – 10922 | 5462 |
| Node C (Master) | 10923 – 16383 | 5461 |
设计意图: 16384 这个数字是经过权衡的——它足够大以支持大规模集群(最多 1000 个节点),又足够小以在心跳包中高效传递位图(2KB)。
4.2 节点通信:Gossip 协议
Redis Cluster 节点之间通过 Gossip 协议 进行通信,使用 TCP 总线端口(默认是服务端口 +10000)。每个节点定期向其他节点发送 PING 消息,并接收 PONG 响应,以此交换集群的元数据(如节点状态、槽位信息、主从关系)。
Gossip 消息类型
| 消息类型 | 作用 |
|---|---|
| PING | 探测节点是否存活,并携带本节点已知的集群信息 |
| PONG | 对 PING 的响应,包含本节点的完整状态 |
| MEET | 邀请新节点加入集群 |
| FAIL | 广播某个节点已下线 |
| UPDATE | 通知其他节点更新槽位映射信息 |
注意: 如果集群节点数超过 1000,Gossip 消息量会显著增加。建议通过
cluster-node-timeout 和 cluster-require-full-coverage 参数进行调优,避免网络拥塞。
4.3 集群伸缩:在线扩缩容
Redis Cluster 支持在不停止服务的情况下进行在线扩容和缩容。核心操作是槽位迁移(Slot Migration),即将一部分哈希槽及其数据从一个节点迁移到另一个节点。
扩容流程
- 添加节点: 使用
CLUSTER MEET命令将新节点加入集群。 - 分配槽位: 使用
CLUSTER ADDSLOTS或redis-cli --cluster reshard将部分槽位从现有节点迁移到新节点。 - 数据迁移: 源节点将槽位内的键逐步导出,目标节点导入。迁移过程中,客户端访问该槽位时,节点会返回
MOVED或ASK重定向指令。 - 完成: 槽位所有权变更后,集群状态更新。
缩容流程
- 迁移槽位: 将待下线节点的所有槽位迁移到其他节点。
- 忘记节点: 使用
CLUSTER FORGET命令从集群中移除该节点。 - 关闭节点: 停止 Redis 进程。
关键命令:
redis-cli --cluster reshard <host>:<port> 是官方推荐的交互式槽位重分配工具。
4.4 集群架构总览
下图展示了 Redis Cluster 的典型架构,包含 3 个主节点和 3 个从节点,以及客户端通过哈希槽进行数据路由的过程。
4.5 关键配置与最佳实践
| 配置项 | 默认值 | 说明 |
|---|---|---|
cluster-enabled yes |
no | 启用集群模式 |
cluster-config-file |
nodes.conf | 集群状态持久化文件 |
cluster-node-timeout |
15000 | 节点超时时间(毫秒),影响故障检测速度 |
cluster-require-full-coverage |
yes | 是否要求所有槽位都被覆盖才能提供服务 |
cluster-migration-barrier |
1 | 主节点至少保留的从节点数量,用于副本迁移 |
生产建议: 将
cluster-require-full-coverage 设为 no,避免因少数节点故障导致整个集群不可用。同时,确保每个主节点至少有一个从节点,以实现高可用。
4.6 客户端路由:MOVED 与 ASK
当客户端请求的键不在当前节点时,节点会返回重定向信息:
- MOVED: 槽位已永久迁移到另一个节点。客户端应更新本地缓存的路由表,直接访问新节点。
- ASK: 槽位正在迁移中。客户端需要先向目标节点发送
ASKING命令,再发送原请求。
代码示例: 客户端处理 MOVED 重定向
# 假设客户端连接到节点 127.0.0.1:7000,请求 key:user:1001
127.0.0.1:7000> GET user:1001
-MOVED 12345 127.0.0.1:7002
# 客户端解析 MOVED 响应,更新本地槽位映射,重新发送请求到 127.0.0.1:7002
127.0.0.1:7002> GET user:1001
"value_1001"
4.7 本章小结
Redis Cluster 通过哈希槽分片实现了数据的水平扩展,利用Gossip 协议保证了集群状态的一致性,并支持在线伸缩。理解这些核心机制是构建高可用、高吞吐缓存架构的基础。在实际应用中,需重点关注槽位迁移对客户端的影响,以及集群网络分区时的行为。