Redis--基础知识点--31--集群哈希槽为什么是16384?

1 说法一

因为CRC16会输出16bit的结果,可以看作是一个分布在 0~2^16-1 之间的数,redis的作者测试发现这个数对 2^14 求模的会将key在 0-2^14-1 之间分布得很均匀, 2^14 即16384

2 说法二

为了节省存储空间,每个节点用一个Bitmap记录节点对应的槽 ,2k = 210248 = 16384,也就是说,每个节点用2k的内存空间,总共16384个比特位,就可以存储该结点对应了哪些槽。

Bitmap记录节点对应的槽 有两个作用:

  • 判断key是不是归于当前节点,当一个客户端发送来一个key时,通过CRC(16) / 16384 计算出该key归属的槽solt,然后计算检查 (myslots[slot>>3] >> (slot&7)) & 1,一条位运算指令判断key是不是归于当前节点。[只需要了解即可,不用追究位运算细节]
  • redis Cluster 节点之间通过 Gossip 消息同步集群状态。每个节点需要定期广播 自己负责的槽位集合,以便其他节点更新全局槽映射表 。如果直接发送槽号列表(如 [0,1,2,...5000])需要成千上万个整数(几 KB 到几十 KB),而发送一个 2KB 的位图 就能完整表示所有槽的归属,网络开销小且固定

补充:

  • 全局槽映射表:它是一个长度为 16384 的数组,数组的下标是槽号(0~16383) ,对应的值是该槽归属的主节点信息(通常是指向节点结构体的指针,或者节点ID)。用途:客户端请求到达任意节点时,节点查这个表知道该把请求转发给谁(或返回 MOVED)。

问:已经有全局槽映射表为什么还需要bitmap表示节点自身有哪些槽位?

很好的问题!表面上看确实有冗余,但两者服务不同的场景和需求,同时存在是为了性能、消息传输和代码逻辑的清晰

1. 本质上的信息重叠与用途分离

  • 全局槽映射表slots[16384]):记录 每个槽由哪个节点负责
    用途:客户端请求到达任意节点时,节点查这个表知道该把请求转发给谁(或返回 MOVED)。
  • 每个节点的位图myslots,2KB):记录 当前节点负责哪些槽
    用途:快速判断"这个槽是不是我管的",以及集群内部通信时高效地 告诉别人我管哪些槽

虽然 slots[slot] == myself 也能判断是否自己负责,但位图有独特优势。

2. 性能:位操作比指针比较更轻量

判断一个槽是否属于当前节点:

  • 用位图:检查 (myslots[slot>>3] >> (slot&7)) & 1,一条位运算指令。
  • 用全局表:读取 slots[slot](一个指针),然后与 myself 指针比较,需要两次内存访问和一次比较。

在极高并发(如每秒几十万请求)下,位图的微秒级优势会被放大。更重要的是,Redis 常需要 批量判断 (如计算自己负责的槽总数、遍历所有属于自己的槽进行迁移),用位图可以用 memcpy、位计数(popcount)等高效操作,比循环检查 16384 个数组元素快得多。

3. 消息传输:位图是 Gossip 协议的压缩载体

Redis Cluster 节点之间通过 Gossip 消息同步集群状态。每个节点需要定期广播 自己负责的槽位集合 ,以便其他节点更新全局表。如果直接发送槽号列表(如 [0,1,2,...5000])需要成千上万个整数(几 KB 到几十 KB),而发送一个 2KB 的位图 就能完整表示所有槽的归属,网络开销小且固定。

其他节点收到位图后,只需按位解析就能重构该节点的槽信息,并更新自己的全局映射表。

4. 容错和独立性

全局映射表是一个 逻辑汇总视图 ,可能因为消息延迟或丢包暂时不一致。而每个节点自身维护的位图是 权威数据 (节点自己知道确切负责哪些槽)。当节点发现全局表中的某些槽与自己位图不一致时,会触发修复(如通过 CLUSTER BUMPEPOCH 或配置更新)。

5. 历史与代码组织

Redis 最早实现集群时就设计了 clusterNode->slots 位图(每个节点负责的槽),后来为了方便全局路由才增加了 server.cluster->slots 数组。两个结构并存,各有调用场景:

  • 需要"给定槽 → 节点"时用全局数组。
  • 需要"给定节点 → 它负责的槽集合"时用该节点的位图。

总结

不是"有了全局表就不需要位图",而是两者从不同维度建模数据

  • 全局表是 槽为中心(槽 → 节点),加速路由。
  • 位图是 节点为中心(节点 → 槽集合),加速节点自身的判断、迁移和 Gossip 广播。

内存占用上,每个节点多 2KB 完全可接受,带来的性能、网络和代码清晰度收益却很大。如果去掉位图,许多操作会变得笨拙且低效。

相关推荐
SeSs IZED2 小时前
MySQL中查看表结构
数据库·mysql·oracle
北冥有羽Victoria2 小时前
Django Auth组件完整版教程:从原理到项目落地
大数据·服务器·数据库·后端·python·django·sqlite
ZGi.ai2 小时前
自然语言查数据库:Text-to-SQL工程实现与企业落地细节
数据库·sql·nl2sql·text-to-sql
旷世奇才李先生2 小时前
Redis 7\.x实战:缓存设计与分布式锁实现
redis·分布式·缓存
JSON_L3 小时前
Fastadmin中实现敏感词管理
数据库·php·fastadmin
不是起点的终点4 小时前
【实战】Python 一键生成数据库说明文档(对接阿里云百炼 AI,输出 Word 格式)
数据库·python·阿里云
2301_813599556 小时前
Go语言怎么做秒杀系统_Go语言秒杀系统实战教程【实用】
jvm·数据库·python
NCIN EXPE10 小时前
redis 使用
数据库·redis·缓存
MongoDB 数据平台10 小时前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb