Redis Cluster 核心原理:哈希槽与数据路由实战

在 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 时:

  1. 有效部分是 num
  2. 计算 CRC16("num") % 16384,结果为 2765。
  3. 2765 在 0-5460 范围内,属于 7001 节点。
  4. 结果:数据直接存储在 7001。

场景二:触发重定向

当我们执行 SET a 1 时:

  1. 有效部分是 a
  2. 计算 CRC16("a") % 16384,结果为 15495。
  3. 15495 在 10923-16383 范围内,属于 7003 节点。
  4. 结果:7001 节点发现该槽位不归自己管,会返回一个 MOVED 错误,告诉客户端:"去 7003 节点找"。客户端收到后会自动跳转。

场景三:利用哈希标签

如果我们执行 SET {a}number 1

  1. 有效部分变成了 {} 中的 a
  2. 计算结果依然是 15495(因为有效部分还是 a)。
  3. 结果:数据被路由到 7003 节点。
进阶技巧:哈希标签的商业价值

你可能会问,为什么要设计 {} 这种机制?难道就是为了把数据存到别的节点吗?当然不是。哈希标签是解决"跨槽操作"难题的钥匙。

在 Redis 集群中,涉及多个 Key 的操作(如 MGETMSET 或 事务)要求所有 Key 必须在同一个槽位上,否则会报错。

应用场景:商品分类存储

假设我们要存储用户 1001 的姓名、年龄和城市。为了保证事务的一致性,我们需要它们存储在同一个节点上。

  • SET {user:1001}:name "Alice"
  • SET {user:1001}:age 25
  • SET {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 取模。
  • 利用 {} 哈希标签,我们可以强制将相关联的数据"捆绑"在同一个节点,从而支持批量操作和事务,这是生产环境优化的关键技巧。
相关推荐
Java开发的小李13 小时前
SpringBoot + Redis 实现分布式 Session 共享(解决多实例登录状态丢失问题)
spring boot·redis·分布式
Old Uncle Tom13 小时前
OpenClaw 记忆系统 -- 记忆预加载
java·数据结构·算法·agent
会编程的土豆13 小时前
洛谷题单入门1 顺序结构
数据结构·算法·golang
生信碱移13 小时前
PACells:这个方法可以鉴定疾病/预后相关的重要细胞亚群,作者提供的代码流程可以学习起来了,甚至兼容转录组与 ATAC 两种数据类型!
人工智能·学习·算法·机器学习·数据挖掘·数据分析·r语言
智者知已应修善业14 小时前
【51单片机中的打飞机设计】2023-8-25
c++·经验分享·笔记·算法·51单片机
daixin884815 小时前
cursor无法正常使用gpt5.5等模型解决方案
java·redis·cursor
智者知已应修善业16 小时前
【51单片机按键调节占空比3位数码管显示】2023-8-24
c++·经验分享·笔记·算法·51单片机
小猿姐16 小时前
Redis Kubernetes Operator 实测:三个方案的真实差距
redis·容器·kubernetes
.54817 小时前
## Sorting(排序算法)
python·算法·排序算法
wuweijianlove17 小时前
算法的平均复杂度建模与性能回归分析的技术7
算法·数据挖掘·回归