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,然后计算检查 (myslotsslot\>\>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 完全可接受,带来的性能、网络和代码清晰度收益却很大。如果去掉位图,许多操作会变得笨拙且低效。

相关推荐
金海境科技2 小时前
【服务器数据恢复】H3C CAS虚拟化平台HP存储qcow2文件损坏快照丢失数据恢复案例
服务器·数据库·经验分享
正儿八经的少年2 小时前
Spring 事务保证数据一致性
java·数据库·spring
foo1st2 小时前
MySQL 8.0(Windows)升级笔记
数据库·笔记·mysql
张人玉2 小时前
基于 Vue 3 + ECharts + Express + SQLite 的可视化大屏与业务管理系统——YOLOv8 高精度车辆行人检测与计数系统
数据库·vue.js·yolo·sqlite·echarts·express
吴声子夜歌2 小时前
MongoDB 4.x——高级特性(Change Stream和事务)
数据库·mongodb
是店小二呀2 小时前
NanoPi R4S怎么搭私人云盘?iStoreOS与WebDAV完整教程
数据库·人工智能
Database_Cool_2 小时前
云数据库备份是怎么实现的、支持时间点恢复吗:阿里云 RDS MySQL 备份与 PITR 详解
数据库·mysql·阿里云
名字还没想好☜3 小时前
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路
开发语言·数据库·golang·go·并发
NWU_LK3 小时前
【WebFlux】第六篇 —— 全链路响应式与数据库交互
java·数据库
叶总没有会3 小时前
3.2 构建AI智能体项目扩展知识
java·数据库·人工智能·spring·ai