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 取模。
  • 利用 {} 哈希标签,我们可以强制将相关联的数据"捆绑"在同一个节点,从而支持批量操作和事务,这是生产环境优化的关键技巧。
相关推荐
智者知已应修善业14 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业14 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机
AI算法沐枫14 小时前
大模型 | 大模型之机器学习基本理论
人工智能·python·神经网络·学习·算法·机器学习·计算机视觉
吃着火锅x唱着歌14 小时前
LeetCode 1019.链表中的下一个更大节点
算法·leetcode·链表
Tirzano15 小时前
超大型组和用户缓存redis
redis·缓存·哈希算法
凌波粒15 小时前
LeetCode--404.左叶子之和(二叉树)
算法·leetcode·职场和发展
paeamecium15 小时前
【PAT甲级真题】- A+B in Hogwarts
c++·算法·pat考试·pat
阿维的博客日记15 小时前
zset实现延迟队列
redis·zset
青山师15 小时前
二叉树与BST深度解析:遍历算法与平衡策略
数据结构·算法·面试·二叉树·算法与数据结构·java面试·数据结构与算法分析