目标
理解一下 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;
- ❌ 部分命令受限(如
KEYS
、SCAN
)。
🧠 小结
设计目标 | Redis Cluster 的方案 |
---|---|
水平扩展 | 通过 slot 自动分片 |
动态扩容 | slot 可迁移 |
容错恢复 | 节点间 gossip 通信 + 选举 |
客户端直连 | CRC16 计算 slot |
无中心架构 | 每个节点都知道拓扑 |
所以,Redis Cluster 的 slot 机制本质上是一种工程上的优雅平衡:
既保证了分布式可扩展性,又保留了 Redis 单机的极致性能。
小结
理解为什么这样,反而比直接知道答案更加重要。