适用版本:Redis 7.2.x
当业务规模继续增大,单个 Redis 主库哪怕配了多个从库,也还是会遇到一个核心瓶颈:
- 内存容量有上限;
- 单机 CPU 有上限;
- 单主写入能力也有上限。
这时候,仅靠主从复制和 Sentinel 已经不够了。因为它们解决的是高可用,而不是横向扩容。
Redis Cluster(集群)就是 Redis 官方提供的分布式分片方案。它把数据拆散到多个主节点上,每个主节点再带自己的副本,从而同时解决两类问题:
- 容量扩展:数据不再塞进一台机器;
- 高可用:每个主节点都有副本,主故障时可以自动切换。
这篇文章会重点讲清楚 Cluster 的基础模型:哈希槽、节点角色、请求路由、重定向机制、创建方式与使用边界。只要把这些底层逻辑搞明白,后面再学扩缩容、迁槽、故障处理就会顺很多。
一、Redis Cluster 解决的核心问题是什么
先看一个问题。
如果只有 Sentinel 模式,即使你有:
- 1 个主库
- 2 个从库
- 3 个哨兵
你仍然只有一个写主。数据再多、写入再高,压力还是集中在一个主节点上。
而 Redis Cluster 的目标,是把数据和流量分散到多个主节点。
1. 从“单主复制”变成“多主分片”
Cluster 不是一个主库加很多从库,而是:
- 多个主节点共同组成一个逻辑集群;
- 每个主节点负责一部分数据;
- 每个主节点再有自己的副本,用于故障转移。
2. 同时兼顾扩展与可用
因此 Redis Cluster 可以理解为:
分片能力 + 副本高可用能力 的组合。
二、Cluster 的整体架构图景
一个最小可用的 Redis Cluster,通常至少是 3 主 3 从。
+----------------------+
| Client |
| 感知集群拓扑并路由请求 |
+----------+-----------+
|
+--------------------+--------------------+
| | |
v v v
+---------+ +---------+ +---------+
| Master1 | | Master2 | | Master3 |
|槽位0~5k | |槽位5k~10k| |槽位10k~16k|
+----+----+ +----+----+ +----+----+
| | |
v v v
+---------+ +---------+ +---------+
|Replica1 | |Replica2 | |Replica3 |
+---------+ +---------+ +---------+
在这个结构里:
- 每个 master 负责一部分槽位和数据;
- 每个 replica 复制对应主节点的数据;
- 客户端不再只盯住单台 Redis,而是要理解整个集群拓扑。
这也是 Redis Cluster 和 Sentinel 最大的使用差异之一:
Cluster 客户端必须具备集群路由能力。
三、哈希槽:Cluster 的核心设计
Redis Cluster 没有采用“直接按节点数量做哈希”的方式,而是引入了 16384 个哈希槽(hash slots)。
1. 什么是哈希槽
可以把它理解成:
- 整个集群预先划分好 16384 个桶;
- 每个 key 先映射到某个槽;
- 槽再归属于某个主节点。
例如:
key -> CRC16(key) % 16384 -> slot -> 某个 master 节点
2. 为什么要引入槽位,而不是直接 key -> node
因为这样做有明显好处:
- 节点扩缩容时,迁移的是槽位,不是重新整体洗牌;
- 集群拓扑变化更容易管理;
- 数据迁移粒度更清晰。
3. 一个直观例子
假设:
Master1负责槽位0 ~ 5460Master2负责槽位5461 ~ 10922Master3负责槽位10923 ~ 16383
如果 key user:1001 经过计算落在槽位 8200,那它就归 Master2 负责。
所以 Redis Cluster 的本质不是“key 落在哪台机器”,而是:
key 先落在哪个槽,再由槽决定归属节点。
四、节点角色与副本关系
1. 主节点负责槽位
只有主节点负责持有槽位并处理该槽位的数据写请求。
2. 从节点复制主节点
每个主节点都可以有一个或多个副本。副本默认复制主节点数据,用于高可用切换。
3. 从节点不负责槽位归属
从节点本身不是槽位拥有者,它主要承担:
- 数据副本存储;
- 故障时的主从切换候选;
- 某些读场景下可辅助分流(但要谨慎处理一致性)。
4. Cluster 中也有自动故障转移
如果某个主节点失效,且它有可用副本,集群会尝试让对应副本提升为新的主节点,继续接管原来那批槽位。
所以 Cluster 并不是不要复制,而是:
- 主节点之间负责分片;
- 主从之间负责高可用。
五、客户端为什么必须“懂集群”
在单机 Redis 或 Sentinel 模式下,客户端通常只要找到当前主库即可。
但在 Cluster 模式下,客户端面对的是多个主节点,必须知道:
- 某个 key 对应哪个槽位;
- 这个槽位当前在哪个节点上;
- 如果拓扑变化了,如何刷新路由表;
- 遇到
MOVED或ASK重定向时怎么处理。
这意味着普通的单机 Redis 客户端不能直接无脑连接 Cluster。
一个常见误区
很多新手以为:
Cluster 就是“多台 Redis 放一起”,我连任意一台发命令就行。
其实不对。真正正确的理解是:
客户端需要感知整个槽位与节点的映射关系。
六、请求路由:为什么会出现 MOVED 和 ASK
1. MOVED
如果客户端把某个 key 的请求发到了错误节点,而该节点知道这个槽位已经正式归属其他节点,它会返回类似:
-MOVED 8200 192.168.10.12:6379
含义是:
- 槽位
8200不在我这里; - 它正式属于
192.168.10.12:6379; - 你应该更新路由并去那边访问。
2. ASK
在槽位迁移过程中,一个槽可能处于“正在搬家”的过渡状态。这时节点可能返回:
-ASK 8200 192.168.10.12:6379
它的语义和 MOVED 不一样:
- 这不是长期归属变更;
- 而是一次临时引导;
- 客户端本次请求先去目标节点,并带
ASKING。
3. 为什么要区分两种重定向
因为它们代表不同阶段:
MOVED:槽位已经迁完,路由应长期更新;ASK:槽位还在迁移中,本次请求临时转发即可。
这也是 Cluster 扩缩容时必须理解的关键基础。
七、跨槽问题:为什么有些多 key 命令会报错
Redis Cluster 里一个非常典型的问题就是:
CROSSSLOT Keys in request don't hash to the same slot
1. 原因是什么
因为多 key 操作如果涉及不同槽位,就无法保证在一个节点上完成。
典型场景包括:
MGET key1 key2SUNION set1 set2DEL key1 key2 key3- Lua 脚本访问多个不同槽位的 key
2. 为什么 Redis Cluster 不支持任意跨节点原子操作
因为 Cluster 的目标是高性能分片,而不是分布式事务系统。让不同主节点之间做复杂协同,会显著增加系统复杂度和性能成本。
3. 如何解决:Hash Tag
Redis Cluster 提供了 Hash Tag 机制。
如果 key 中带有同一对花括号 {} 包裹的内容,那么计算槽位时只会对花括号里的部分做哈希。
例如:
order:{1001}:info
order:{1001}:items
order:{1001}:status
这三个 key 会落到同一个槽位,于是你就可以更容易地对它们做多 key 操作。
4. 什么时候适合用 Hash Tag
适合:
- 同一业务实体的多个 key 需要落在一起;
- 明确存在多 key 操作需求;
- 需要局部事务或局部 Lua 脚本操作。
但不要滥用,否则会导致数据过度集中,破坏分片均衡。
八、Redis Cluster 的最小创建方式
通常可以用 redis-cli --cluster 来快速创建测试集群。
假设你已经启动 6 个实例:
700070017002700370047005
每个实例都要至少开启:
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
然后执行:
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
这个命令的含义是:
- 用 6 个节点创建一个集群;
- 每个主节点分配 1 个副本;
- 最终会形成 3 主 3 从。
创建完成后,可以检查集群信息:
redis-cli -p 7000 cluster nodes
redis-cli -p 7000 cluster info
九、常用 Cluster 命令
1. 查看集群整体状态
127.0.0.1:7000> CLUSTER INFO
常关注字段:
cluster_state:是否为ok;cluster_slots_assigned:是否分配完 16384 个槽;cluster_known_nodes:已知节点数量;cluster_size:主节点数量。
2. 查看节点拓扑
127.0.0.1:7000> CLUSTER NODES
可以看到:
- 每个节点 ID;
- 角色是主还是从;
- 从属关系;
- 槽位分布;
- 当前连接状态。
3. 查看某个 key 属于哪个槽
127.0.0.1:7000> CLUSTER KEYSLOT user:1001
(integer) 8200
这个命令很适合排查跨槽问题。
4. 查看某个槽归谁管理
127.0.0.1:7000> CLUSTER SLOTS
能看到槽位范围与节点地址映射关系。
5. 使用集群模式连接客户端
redis-cli -c -p 7000
-c 表示开启集群模式,这样 redis-cli 才能自动处理 MOVED 和部分路由跳转。
十、Cluster 的高可用是怎么实现的
Redis Cluster 内部也有故障检测和主从切换能力。
1. 节点之间会互相通信
Cluster 节点通过集群总线交换状态信息,包括:
- 节点存活情况;
- 槽位归属;
- 故障报告;
- 复制关系。
2. 主节点故障时,副本可提升
如果某个主节点被认为故障,并且存在合格副本,则副本会尝试发起故障转移,成为新的主节点,接管原有槽位。
3. 仍然有异步复制边界
和普通主从一样,Cluster 的副本复制本质上仍然是异步的,所以在故障切换瞬间仍可能损失最近少量未复制完成的数据。
所以需要清楚:
Cluster 提供的是高可用能力,不是强一致分布式数据库语义。
十一、Cluster 的优点与限制
1. 优点
- 支持水平扩容;
- 每个主节点分担部分内存与流量;
- 自带副本高可用能力;
- 官方原生支持,生态成熟。
2. 限制
- 客户端必须支持 Cluster;
- 多 key 操作受槽位限制;
- Lua、事务等操作一般要求 key 落在同一槽;
- 运维复杂度高于单机和 Sentinel;
- 故障切换期间仍可能有短暂不可用或少量数据丢失。
3. 适用场景
Cluster 更适合:
- 数据规模已经超过单机容量;
- 需要多主分片扩容;
- 能接受客户端集群化改造;
- 对高性能 KV 分布式缓存有明确需求。
十二、常见问题
1. Redis Cluster 和 Sentinel 有什么本质区别?
可以简单理解为:
- Sentinel:解决单主架构的自动故障切换;
- Cluster:解决多主分片 + 副本高可用。
如果只是单实例高可用,Sentinel 通常够用;如果单机容量已经不够,才需要 Cluster。
2. 为什么 Redis Cluster 是 16384 个槽,而不是更多?
你可以把它理解为一个在路由粒度、元数据大小、管理复杂度之间做出的平衡设计。对大多数业务场景来说,16384 个槽已经足够细。
3. 为什么我连接某个节点时会收到 MOVED?
因为你请求的 key 不归当前节点负责。正确做法是:
- 使用支持 Cluster 的客户端;
- 或者用
redis-cli -c连接测试。
4. Cluster 能不能完全避免单点问题?
不能完全避免,但能显著降低单点影响。因为每个主节点仍然可能故障,只是它有副本,可以在故障时接管槽位。
5. 为何多 key 命令经常报跨槽错误?
因为这些 key 不在同一槽位。要么重新设计 key,要么用 Hash Tag 把相关 key 放进同槽。
6. 从节点能不能直接承接所有读请求?
可以做读扩展,但要谨慎,因为复制是异步的,存在读到旧数据的可能。对一致性要求高的场景不能想当然地“写主读从”。
十三、实践建议
1. 先想清楚是不是必须上 Cluster
Cluster 不是默认最佳答案。它带来扩展能力,也引入了更高的客户端和运维复杂度。如果数据规模、流量规模还没到单机瓶颈,Sentinel 可能更简单。
2. 提前设计 key 与槽位策略
尤其是:
- 哪些 key 可能需要多 key 操作;
- 哪些业务实体适合用 Hash Tag 聚合;
- 如何避免热点过度集中到单槽。
3. 客户端务必使用原生支持 Cluster 的 SDK
不要在业务里自己手写槽位路由逻辑,除非你非常清楚全部细节。
4. 监控不只看节点,还要看槽位分布
Cluster 的问题很多不是“某台机器挂了”,而是:
- 槽位迁移不均;
- 热点槽位偏斜;
- 某个主节点压力异常;
- 节点间网络抖动。
5. 为后续扩缩容预留心智模型
只要你记住“Cluster 是按槽位管理数据”,后面学迁槽、扩容、缩容、故障转移就会容易很多。
十四、小结
学习 Redis Cluster,最重要的是先建立下面这套认知:
- Cluster 不是单主复制,而是多主分片架构;
- 数据通过
CRC16(key) % 16384映射到哈希槽,再由槽位归属主节点; - 每个主节点再配副本,用于故障切换;
- 客户端必须理解槽位路由,并正确处理
MOVED/ASK; - 多 key 操作通常要求 key 落在同一槽位,必要时可借助 Hash Tag。
如果把这些基础概念掌握住,Redis Cluster 就不会再只是一个“很复杂的分布式名词”,而会变成一个清晰的结构化系统。后续再看集群扩容、缩容、迁槽和故障处理时,你会更容易理解每一步到底在做什么。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!