在 Redis 的高可用架构中,分片集群(Sharding Cluster)解决了单机内存和性能瓶颈。不同于主从哨兵模式,分片集群引入了"哈希槽"的概念,实现了数据的去中心化存储。
今天,我们就来彻底搞懂 Redis 集群是如何通过哈希槽来分配数据,以及如何利用这一机制优化我们的业务存储。
哈希槽:集群的"物流分拣系统"
Redis 集群并没有采用一致性哈希,而是引入了哈希槽的概念。这是一个非常精妙的设计,我们可以把它想象成一个拥有 16384 个格口的物流分拣中心。(有同学可能要问为什么是16384,我特意去搜了下,这是个最佳实践,大小4kb)
总量固定:Redis 集群预定义了 16384 个哈希槽,编号从 0 到 16383。
- 节点映射 :集群中的每个 Master 节点会负责一部分槽位。例如,一个 3 主 3 从的集群,槽位分配可能如下:
- 节点 7001:负责 0 - 5460
- 节点 7002:负责 5461 - 10922
- 节点 7003:负责 10923 - 16383
数据并不是直接绑定在某个节点上,而是绑定在槽位上。这种设计让集群的扩容和缩容变得异常简单------只需要移动槽位即可,无需全量迁移数据。
数据路由:你的数据去哪了?
当我们执行 SET key value 时,Redis 是如何知道该把数据存在哪台机器上的呢?这依赖于一个三步走的计算流程。
第一步:确定"有效部分"
Redis 首先会检查 Key 中是否包含大括号 {}。
- 无大括号 :整个 Key 就是有效部分。例如
num的有效部分就是num。 - 有大括号 :只有大括号
{}内部的内容才是有效部分。例如{itcast}num的有效部分是itcast。
第二步:计算哈希值
利用 CRC16 算法对"有效部分"进行计算,得到一个哈希值。
第三步:取模定位
将哈希值对 16384 取余,得到的余数就是该 Key 所属的槽位编号。
计算公式
SLOT=CRC16(key) & 16383
实战演练:控制数据存储位置
理解了原理,我们来看看在实际操作中会发生什么。假设我们连接到了 7001 节点(使用 redis-cli -c -p 7001,注意 -c 参数开启了智能路由,这个一定不要省略)。
场景一:普通存储
当我们执行 SET num 123 时:
- 有效部分是
num。 - 计算
CRC16("num") % 16384,结果为 2765。 - 2765 在 0-5460 范围内,属于 7001 节点。
- 结果:数据直接存储在 7001。
场景二:触发重定向
当我们执行 SET a 1 时:
- 有效部分是
a。 - 计算
CRC16("a") % 16384,结果为 15495。 - 15495 在 10923-16383 范围内,属于 7003 节点。
- 结果:7001 节点发现该槽位不归自己管,会返回一个
MOVED错误,告诉客户端:"去 7003 节点找"。客户端收到后会自动跳转。
场景三:利用哈希标签
如果我们执行 SET {a}number 1:
- 有效部分变成了
{}中的a。 - 计算结果依然是 15495(因为有效部分还是
a)。 - 结果:数据被路由到 7003 节点。
进阶技巧:哈希标签的商业价值
你可能会问,为什么要设计 {} 这种机制?难道就是为了把数据存到别的节点吗?当然不是。哈希标签是解决"跨槽操作"难题的钥匙。
在 Redis 集群中,涉及多个 Key 的操作(如 MGET、MSET 或 事务)要求所有 Key 必须在同一个槽位上,否则会报错。
应用场景:商品分类存储
假设我们要存储用户 1001 的姓名、年龄和城市。为了保证事务的一致性,我们需要它们存储在同一个节点上。
SET {user:1001}:name "Alice"SET {user:1001}:age 25SET {user:1001}:city "Beijing"
通过将 {user:1001} 作为哈希标签,Redis 在计算槽位时,只会计算 user:1001 的哈希值。因此,这三个 Key 会落入同一个槽位,也就必然在同一个节点上。
知识小结:核心考点速查表
为了方便大家复习,我将本文的重点整理成了下表:
| 知识点 | 核心内容 | 技术实现 | 应用场景 |
|---|---|---|---|
| 哈希槽 | 16384 个槽位分配到集群节点 | CRC16 算法计算 key 的哈希值并取模 | 数据存储位置判定、数据分片 |
| 插槽分配 | 7001: 0-5460 7002: 5461-10922 7003: 10923-16383 | 集群初始化时自动分配 | 实现数据分片存储 |
| Key 路由机制 | 根据有效部分计算插槽值 1. 带 {} 时取括号内内容 2. 无 {} 时取整个 key |
SET number 123 → 2765 插槽 SET {a}number 1 → 15495 插槽 |
自动重定向到正确节点 |
| 数据绑定原理 | 数据与插槽绑定而非节点 | 节点故障时插槽转移 | 保证数据可定位性 |
| 哈希标签 | 控制 key 的有效部分 | SET {mobile}1001 SET {mobile}1002 |
商品分类存储、批量查询优化 |
| 操作命令演示 | 插槽计算 → 重定向节点 → 现象说明 | SET number 123 (7001) SET a 1 (7003, MOVED) SET {a}number 1 (7003) |
验证有效部分变为大括号内容 |
总结
- 集群通过 16384 个槽位实现数据分片。
- 数据路由依赖于
CRC16算法和% 16384取模。 - 利用
{}哈希标签,我们可以强制将相关联的数据"捆绑"在同一个节点,从而支持批量操作和事务,这是生产环境优化的关键技巧。