← 返回题目列表

Redis Cluster 的槽位机制是怎么工作的?

高频 困难 第 23 / 36 题 更新于 2026/07/27
RedisCluster哈希槽分片

简化版

Redis Cluster 把 key 映射到 16384 个哈希槽,每个主节点负责一部分槽位,从而实现数据分片。客户端根据 key 计算槽位并访问对应节点;如果访问错节点,会收到 MOVED 或 ASK 重定向。

详细版

Redis Cluster 的核心点:

  • 集群固定有 16384 个 hash slots;
  • 每个 key 通过 CRC16 计算后映射到某个槽;
  • 每个主节点负责一段槽位;
  • 主节点可以配置从节点做故障转移;
  • 迁移槽位时可以把槽从一个节点移动到另一个节点;
  • 多 key 操作通常要求 key 在同一个槽位。

为了让多个 key 落到同一槽,可以使用 hash tag:

user:{1001}:profile
user:{1001}:orders

花括号中的 1001 会作为计算槽位的部分,因此两个 key 会落在同一个槽。

完整版教学

一、Cluster 解决的是水平分片

主从 + Sentinel 主要解决高可用,但单主节点仍然承载全部数据和写流量。Redis Cluster 把数据分散到多个主节点上,让容量和吞吐可以横向扩展。

它不是按节点数直接对 key 取模,而是引入固定数量的哈希槽。这样扩容、缩容时迁移的是槽位,而不是重新打散所有 key。

如果直接按节点数取模,3 个节点扩到 4 个节点时,大量 key 的映射结果都会变化,迁移成本很高。Cluster 固定 16384 个槽,key 先映射到槽,槽再分配给节点;扩容时只需要把部分槽迁到新节点。这个设计把“key 到节点”的变化收敛为“槽到节点”的变化。

key -> slot -> node

user:1 -> slot 3200  -> node A
user:2 -> slot 11800 -> node C

二、16384 个槽怎么映射 key

Redis Cluster 对 key 计算 CRC16,然后对 16384 取模,得到槽号。集群中每个主节点负责一部分槽。

例如:

key -> slot 5000 -> node A
key -> slot 12000 -> node B

客户端如果知道槽位分布,就可以直接把命令发给正确节点。

公式可以简化写成:

slot = CRC16(key) % 16384

比如 3 个主节点可以大致分配为:A 负责 0-5460,B 负责 5461-10922,C 负责 10923-16383。真实环境不要求连续均分,但必须所有槽都有负责的主节点,否则集群会出现槽未覆盖的问题,相关 key 无法服务。

层级职责
key业务访问对象
slot固定 16384 个逻辑分片
master node负责一批 slot
replica node复制 master,故障时可提升

记忆钩子:Redis Cluster 不是 key 直接找机器,而是 key 先找槽,槽再找机器。

三、MOVED 和 ASK 是什么

如果客户端把命令发错节点,节点会返回 MOVED,告诉客户端这个槽现在属于哪个节点。客户端更新槽位缓存后再请求正确节点。

ASK 常见于槽位迁移过程中,表示这个 key 临时在另一个节点上,需要客户端临时去目标节点询问。MOVED 更像永久重定向,ASK 更像迁移中的临时重定向。

MOVED 通常意味着客户端的槽位表过期了,应刷新本地缓存;ASK 则发生在迁移期间,客户端需要先向目标节点发送 ASKING,再执行命令,但不应因此永久改槽位归属。面试里把这两个区分清楚,可以体现你知道扩缩容迁移过程,而不是只背“会重定向”。

四、多 key 操作为什么受限制

Cluster 下不同 key 可能在不同节点。像 MGET a b、集合交集、Lua 脚本涉及多个 key 时,如果 key 不在同一个槽,单个节点无法原子处理所有数据。

这时可以使用 hash tag,让相关 key 落到同一槽:

cart:{u100}:items
cart:{u100}:total

但 hash tag 不能滥用。如果大量 key 都用同一个 tag,会造成单槽热点,破坏分片均衡。

例如下面两个 key 会按 {u100} 计算槽位,因此可以落到同一槽:

cart:{u100}:items
cart:{u100}:coupon

但如果所有订单 key 都写成 order:{all}:1order:{all}:2,它们都会进入同一槽,Cluster 分片能力基本被废掉。hash tag 适合把确实需要原子多 key 操作的一小组 key 放到一起,不适合把全业务压到一个 tag。

五、Cluster 的高可用边界

Cluster 中每个主节点可以有从节点。主节点故障时,集群可以把对应从节点提升为主节点,继续负责这些槽。

但如果某个主节点及其从节点都不可用,对应槽位无法服务,集群可用性就会受影响。所以生产要合理部署主从、机架和可用区分布。

还要注意 Cluster 不是强一致复制。主从复制仍可能有延迟,主节点刚写入但未复制到从节点时故障,可能存在少量数据丢失风险。Cluster 提供分片和自动故障转移能力,但业务仍要根据数据重要性设计幂等、补偿和持久化方案。

六、扩容迁移时发生什么

扩容时,新节点加入集群后通常会从旧节点迁移一部分槽。迁移过程中,一个槽里的 key 会逐步移动,客户端可能收到 ASK 临时重定向;迁移完成后,槽归属改变,客户端收到 MOVED 并更新槽位缓存。迁移单位是槽,而不是每次都重新计算所有 key 到节点的映射。

扩容前:
node A: slots 0-8000
node B: slots 8001-16383

扩容后:
node C 接收 A/B 的部分 slots
客户端刷新 slot -> node 映射

七、常见误区与追问

  • 误区:Redis Cluster 按节点数对 key 取模。 Cluster 固定 16384 个槽,key 映射到槽,槽再分配给节点。
  • 误区:加节点后热点 key 会自动分散。 单个 key 仍属于一个槽和一个主节点,热点 key 需要本地缓存、副本 key 或业务拆分治理。
  • 误区:hash tag 可以随便用。 hash tag 会让相关 key 落同槽,滥用会制造单槽热点,破坏均衡。
  • 误区:MOVED 和 ASK 是一回事。 MOVED 表示槽归属已变化,需要更新缓存;ASK 是迁移中的临时访问。
  • 追问:为什么多 key 操作要求同槽? 因为 Redis 单节点只能原子处理自己拥有的数据,跨节点多 key 原子性和一致性无法由单个节点保证。
  • 追问:Cluster 能替代 Sentinel 吗? Cluster 自带分片和主从故障转移能力,Sentinel 主要管理非 Cluster 主从;两者解决模型不同,不能简单等同。

八、加强记忆

Redis Cluster 的核心是 16384 个哈希槽:key 通过 CRC16(key) % 16384 找槽,槽再归属某个主节点。客户端缓存槽位表,访问错节点会收到 MOVED,槽迁移中可能收到 ASK。多 key 原子操作要求同槽,可以用 hash tag 控制相关 key,但不能滥用到制造热点。Cluster 解决分片扩容和一定高可用,不会自动消除单 key 热点,也不等于强一致存储。