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),即将一部分哈希槽及其数据从一个节点迁移到另一个节点。

扩容流程

  1. 添加节点: 使用 CLUSTER MEET 命令将新节点加入集群。
  2. 分配槽位: 使用 CLUSTER ADDSLOTS 或 redis-cli --cluster reshard 将部分槽位从现有节点迁移到新节点。
  3. 数据迁移: 源节点将槽位内的键逐步导出,目标节点导入。迁移过程中,客户端访问该槽位时,节点会返回 MOVED 或 ASK 重定向指令。
  4. 完成: 槽位所有权变更后,集群状态更新。

缩容流程

  1. 迁移槽位: 将待下线节点的所有槽位迁移到其他节点。
  2. 忘记节点: 使用 CLUSTER FORGET 命令从集群中移除该节点。
  3. 关闭节点: 停止 Redis 进程。
关键命令: redis-cli --cluster reshard <host>:<port> 是官方推荐的交互式槽位重分配工具。

4.4 集群架构总览

下图展示了 Redis Cluster 的典型架构,包含 3 个主节点和 3 个从节点,以及客户端通过哈希槽进行数据路由的过程。

Redis Cluster 架构与数据路由 客户端 CRC16(key) % 16384 Master A 槽位: 0-5460 Slave A1 Master B 槽位: 5461-10922 Slave B1 Master C 槽位: 10923-16383 Slave C1 Slave A2 (备) Slave B2 (备) Slave C2 (备) Gossip 协议 说明:客户端计算 key 的哈希槽后,直接连接对应主节点;主节点间通过 Gossip 协议交换状态;从节点异步复制主节点数据并提供读服务。

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 协议保证了集群状态的一致性,并支持在线伸缩。理解这些核心机制是构建高可用、高吞吐缓存架构的基础。在实际应用中,需重点关注槽位迁移对客户端的影响,以及集群网络分区时的行为。