目标

理解一下 redis 集群模式设计时候的取舍

chat

为什么 redis cluster 模式要这么设计?分布式集群有哪些方案,各有哪些取舍

非常好的问题,这个其实涉及到 Redis Cluster 的底层原理 + 分布式系统设计哲学。我们可以把问题分成两部分:
1️⃣ Redis 为什么要采用 slot 分片的 cluster 设计
2️⃣ 其他分布式集群方案有哪些(比如一致性哈希、中心路由、代理层等),以及它们的取舍。


🧩 一、为什么 Redis Cluster 要采用 Slot 分片设计

1. 核心目标:自动分片 + 自动故障转移 + 无中心化依赖

Redis 作者设计 cluster 的初衷,是让 Redis 天然支持水平扩展,而不依赖任何中心组件(比如 ZooKeeper 或 proxy)。

所以他设计了:

  • 每个节点知道整个集群的拓扑;
  • 客户端可以自己计算 slot;
  • key → slot → node 的映射是纯算法计算,而不是查表;
  • 节点之间可以相互感知(Gossip 协议),自动迁移 slot、故障转移。

👉 也就是说:Redis Cluster 是一个去中心化、自治型分布式系统


2. Slot 是 Redis Cluster 的“核心抽象”

Cluster 模式把整个 key 空间(2^32)压缩成 16384 个 slot

  • 每个节点负责一部分 slot;
  • key 映射到 slot 的规则固定:
    slot = CRC16(key) % 16384
    
  • 客户端只要知道某个 slot 在哪个节点,就能直接找到 key。

例如:

节点A 管理 slot 0-5460
节点B 管理 slot 5461-10922
节点C 管理 slot 10923-16383

这样,新增或迁移节点时,只要调整部分 slot 的归属,不用重新分布所有 key。

迁移粒度从 key 降到了 slot

3. 为什么不采用“一致性哈希”?

一致性哈希是很多分布式缓存(如早期的 Memcached 集群)常用的方式,但 Redis 作者没有用它,原因如下:

对比维度 一致性哈希 Redis Slot 分片
哈希环结构 每个节点一个区间 固定16384个slot
数据迁移 节点增减时需重新计算hash slot迁移即可
客户端复杂度 客户端需维护hash环 由Redis自动管理
重平衡粒度 按节点 按 slot,更小
故障恢复 需要额外协调组件 内建gossip选主机制
实现复杂度 较低 较高,但更可靠

👉 Redis 设计 slot,是为了:

  • 降低 rehash 带来的“全量迁移成本”;
  • 允许部分 slot 的平滑迁移;
  • 更方便 failover 与 slot 迁移。

4. 为什么 16384 不是别的数字?

16384 = 2^14,是一个折中选择:

  • 数量足够大,可以精细分布数据;
  • 数量足够小,便于节点管理(不会像上百万 slot 那样性能低);
  • CRC16 算法配合 16384 的模运算,简单高效。

🧱 二、分布式集群的几种常见方案与取舍

模式 示例系统 优点 缺点
客户端分片 早期 Memcached 客户端自己决定 key → 节点 客户端逻辑复杂,无法动态扩容
代理层分片 Codis、Twemproxy 代理集中路由请求 增加一跳网络,代理层可能成为瓶颈
一致性哈希分片 Hazelcast、Cassandra(早期) 无需中心节点,平衡性好 扩容需大量迁移,复杂度高
固定 slot 分片(Redis Cluster) Redis Cluster 可动态迁移、可感知拓扑、无中心 不支持 pipeline 跨 slot、事务受限
目录服务式分片 MongoDB Router、TiDB PD 路由由中心组件维护 中心化依赖强,容错性差

Redis Cluster 的取舍是:

  • ✅ 不依赖外部协调服务;
  • ✅ 拥有高可用、自动分片;
  • ❌ 无法跨 slot 执行事务、pipeline;
  • ❌ 部分命令受限(如 KEYSSCAN)。

🧠 小结

设计目标 Redis Cluster 的方案
水平扩展 通过 slot 自动分片
动态扩容 slot 可迁移
容错恢复 节点间 gossip 通信 + 选举
客户端直连 CRC16 计算 slot
无中心架构 每个节点都知道拓扑

所以,Redis Cluster 的 slot 机制本质上是一种工程上的优雅平衡

既保证了分布式可扩展性,又保留了 Redis 单机的极致性能。

小结

理解为什么这样,反而比直接知道答案更加重要。