当前位置: 首页 > news >正文

Redis 中 Intset 的内存结构与存储机制详解

Intset(整数集合)是 Redis 为高效存储小整数集合设计的紧凑数据结构,其内存布局和存储方式紧密围绕 "节省空间" 和 "操作高效" 两个核心目标。下面结合结构体定义、内存分配和实际存储案例,完整解析其工作原理:

一、Intset 整体结构与内存布局

Intset 的结构体定义看似简单,实则包含了动态适配不同整数范围的关键设计:

c

typedef struct intset {uint32_t encoding;  // 编码方式(决定元素类型)uint32_t length;    // 元素数量int8_t contents[];  // 柔性数组(实际存储元素)
} intset;

内存总分配规则

一个 Intset 占用的总内存 = 固定头部(8 字节) + 元素数据区(动态大小)

  • 固定头部:encoding(4 字节) + length(4 字节),共 8 字节。
  • 元素数据区:由 contents 柔性数组实现,大小 = length × 单个元素字节数(单个元素字节数由 encoding 决定)。

二、encoding 与 contents 的关联:动态适配整数范围

contents 数组的实际类型完全由 encoding 字段决定,这是 Intset 节省内存的核心机制:

encoding 常量对应类型单个元素字节数整数范围
INTSET_ENC_INT16int16_t2 字节-32768 ~ 32767
INTSET_ENC_INT32int32_t4 字节-2147483648 ~ 2147483647
INTSET_ENC_INT64int64_t8 字节-9223372036854775808 ~ 9223372036854775807

关键细节:int8_t contents[] 的本质

  • 声明为 int8_t 仅为 C 语言语法兼容(柔性数组需声明为字符类型),实际使用时会根据 encoding 强制转换为对应类型的数组(如 int16_t*)。
  • 例如:当 encoding=INTSET_ENC_INT32 时,contents 会被当作 int32_t 数组使用,每个元素占 4 字节。

三、实例解析:从内存布局看元素存储

以具体案例说明 Intset 的内存分配和元素存储方式:

案例 1:存储 [1, 3, 5](使用 INTSET_ENC_INT16 编码)

  1. 头部信息

    • encoding = 2(INTSET_ENC_INT16 的宏定义值),占 4 字节 → 0x00000002
    • length = 3(3 个元素),占 4 字节 → 0x00000003
  2. 元素数据区

    • 每个元素为 int16_t 类型(2 字节),总大小 = 3×2 = 6 字节。
    • 元素按从小到大排序,存储为:
      • 1 → 0x0001(int16_t 表示)
      • 3 → 0x0003
      • 5 → 0x0005
  3. 完整内存布局(小端字节序,按字节偏移量排列):

    plaintext

    偏移量  字节内容(十六进制)  说明
    0-3     02 00 00 00         encoding(INTSET_ENC_INT16)
    4-7     03 00 00 00         length(3个元素)
    8-9     01 00               元素1:1(int16_t)
    10-11   03 00               元素2:3(int16_t)
    12-13   05 00               元素3:5(int16_t)
    

    总内存:8 + 6 = 14 字节。

案例 2:插入 65535 后升级为 INTSET_ENC_INT32

当插入 65535(超出 int16_t 范围),Intset 会触发升级:

  1. 升级后头部信息

    • encoding = 4(INTSET_ENC_INT32),占 4 字节 → 0x00000004
    • length = 4(新增一个元素),占 4 字节 → 0x00000004
  2. 元素数据区

    • 每个元素为 int32_t 类型(4 字节),总大小 = 4×4 = 16 字节。
    • 原有元素升级为 int32_t 并保持排序,新增元素插入末尾:
      • 1 → 0x00000001(int32_t 表示)
      • 3 → 0x00000003
      • 5 → 0x00000005
      • 65535 → 0x0000FFFF
  3. 升级后内存布局

    plaintext

    偏移量  字节内容(十六进制)  说明
    0-3     04 00 00 00         encoding(INTSET_ENC_INT32)
    4-7     04 00 00 00         length(4个元素)
    8-11    01 00 00 00         元素1:1(int32_t)
    12-15   03 00 00 00         元素2:3(int32_t)
    16-19   05 00 00 00         元素3:5(int32_t)
    20-23   FF FF 00 00         元素4:65535(int32_t)
    

    总内存:8 + 16 = 24 字节。

四、元素访问机制:如何正确解析 contents 数组

Redis 通过宏函数 _intsetGet 按编码解析元素,核心逻辑如下:

c

static int64_t _intsetGet(intset *is, uint32_t pos) {// 根据当前编码解析指定位置的元素if (is->encoding == INTSET_ENC_INT64) {return ((int64_t*)is->contents)[pos];  // 按int64_t访问} else if (is->encoding == INTSET_ENC_INT32) {return ((int32_t*)is->contents)[pos];  // 按int32_t访问} else {return ((int16_t*)is->contents)[pos];  // 按int16_t访问}
}

  • 强制类型转换:将 int8_t* 转换为当前编码对应的类型指针(如 int32_t*),直接通过索引访问元素。
  • 字节序兼容:通过 memrevXXifbe 函数处理大端 / 小端字节序差异,保证跨平台一致性。

五、总结:Intset 的设计精髓

  1. 动态编码:根据元素范围自动选择最小可行的编码,避免内存浪费。
  2. 紧凑存储:柔性数组 + 无额外元数据,内存利用率接近 100%。
  3. 有序性:元素始终排序,支持二分查找(O (log n) 复杂度)。
  4. 升级不可逆:只支持从窄编码升级到宽编码(如 int16→int32),保证数据安全。

这种设计让 Intset 在存储小整数集合时,比哈希表节省大量内存(无键值对开销、无指针开销),是 Redis 内存优化的典型案例。当元素数量超过阈值(默认 512)或包含非整数时,Redis 会自动将 Intset 转换为哈希表,平衡内存与性能。


文章转载自:

http://AUswJ1aA.mftzm.cn
http://M8QelBbX.mftzm.cn
http://5Xixi7cG.mftzm.cn
http://9mlp1o28.mftzm.cn
http://LiZmWFbP.mftzm.cn
http://JDM83ELQ.mftzm.cn
http://2an9Ax74.mftzm.cn
http://fwbaBavG.mftzm.cn
http://hfbf90RV.mftzm.cn
http://gprGbLVb.mftzm.cn
http://9fKQGhQo.mftzm.cn
http://nJQegQMV.mftzm.cn
http://i0hZSOz8.mftzm.cn
http://WsNh5Oas.mftzm.cn
http://bbKxqvlZ.mftzm.cn
http://MaFfMG9T.mftzm.cn
http://mg3YbAtk.mftzm.cn
http://Tg3Qs42U.mftzm.cn
http://9f1I7HHM.mftzm.cn
http://uoJmzB2r.mftzm.cn
http://hnooF5eM.mftzm.cn
http://p3HA8ou7.mftzm.cn
http://jY0QqgYz.mftzm.cn
http://Hy4tu5A3.mftzm.cn
http://IuoIoKaJ.mftzm.cn
http://8TQWlzEn.mftzm.cn
http://5VArACg6.mftzm.cn
http://LC7J0oPS.mftzm.cn
http://5wHEky85.mftzm.cn
http://dGxcfNNQ.mftzm.cn
http://www.dtcms.com/a/387092.html

相关文章:

  • uniapp打包前端项目
  • cka解题思路1.32-3
  • 如何解决模型的过拟合问题?
  • 2025牛客周赛108场e题
  • 【课堂笔记】复变函数-2
  • 25、优化算法与正则化技术:深度学习的调优艺术
  • qt QCategoryAxis详解
  • 云游戏时代,游戏盾如何保障新型业务的流畅体验
  • 【Block总结】LRSA,用于语义分割的低分辨率自注意力|TPAMI 2025
  • PY32MD310单片机介绍 电机控制专用,内置三相半桥栅极驱动器
  • Ubuntu服务器挖矿病毒清理
  • 【数据结构】——二叉树
  • 《怪物猎人 荒野》总整理:预载和开放时间、登场怪物
  • web服务解析案例
  • 莫烦Python基础笔记(部分)
  • ACP(四):RAG工作流程及如何创建一个RAG应用
  • qgis导入cad怎么做?
  • 在线图书借阅平台的设计与实现 —— 基于飞算JavaAI的实战开发全流程与优化实践(架构设计与核心模块开发)
  • Spring Cloud - 面试知识点(服务雪崩)
  • 【JQ】使用JS在前端达到存储cookie的效果
  • Git企业开发--分支管理
  • LoRaWAN方案详解:2025年LoRaWAN技术创新与行业发展趋势
  • 【Leetcode hot 100】108.将有序数组转换为二叉搜索树
  • 打包数据集解析及大模型强化学习拓展阅读(96)
  • 软考-系统架构设计师 系统分析与设计详细讲解
  • 什么是信创产品?信创产品认证有哪些标准?
  • docker和虚拟机对比
  • AI: Android 运行ONNX模型
  • transformer各层的输入输出
  • lvgl图形库和qt图形库比较