第6章 整数集合

理解intset的有序连续存储、编码升级、重排插入和不支持降级的空间权衡 覆盖6个正式节点,并以Redis 3.0源码、故障和恢复对账验收。

学习目标

  • 能说明整数集合的有序紧凑存储
  • 能解释类型升级机制与只升不降规则
  • 能判断整数集合的适用数据规模

为什么从“整数集合编码升级台”开始

第6章 整数集合的核心任务是理解intset的有序连续存储、编码升级、重排插入和不支持降级的空间权衡。命令返回值只暴露外层合同;实现解释还必须连接内存结构、写入与读取路径、事件顺序以及失败后的旧状态回收。整数集合编码升级台把这些关系放进同一条可复位轨迹。

先写预测:当新值范围由“int32”进入“int64”时,哪个可观察状态最先变化?再规定什么结果会推翻当前解释。交互中的分数只表达透明因果方向,不冒充真实Redis测量。

来源、版次与独立重写边界

黄健宏作者读者服务页确认正式出版新版以Redis 3.0为源码基线,列出4部分、24章及完整小节,并链接Redis 3.0中文注释源码。本课程据此映射24个正式单元、145个目录节点,另设学习地图和总复习;未取得出版正文授权,目录只界定范围,不宣称复现原书正文。

本章字段与控制流由Redis官方3.0源码:intset.c和作者注释源码交叉核对;Redis当前持久化文档只用于辨认版本差异。中文解释、图示、交互、实验与答案均为独立教学重写,不把目录页或代码仓库许可证误报为原书许可证。

本章术语与源码合同

第6章 整数集合必须守住“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”。观察同时记录整数集合编码升级台一致率与插入位置分叉风险;只有结构快照、函数入口、运行结果和故障反例互相一致,才接受实现结论。

⚡ 整数集合升级过程可视化
intset:有序无重复数组 + 类型升级当前编码:int16_t(每元素 2 字节,范围 -32768 ~ 32767encoding=int16 · length=5 · 总内存 18 字节1020304050每元素 2 字节 × 5 = 10 字节(+ 8 字节头部)添加超出当前编码范围的元素时,整个数组一次性升级到更宽编码
整数集合只支持整数且元素不多时使用(集合键配置 intset-max-entries 内)。升级后不降级:即使超宽元素被删除,编码保持更宽类型——避免频繁升降级的抖动成本。
操作日志
  1. 1.初始整数集合:{10, 20, 30, 40, 50},编码 int16(每元素 2 字节)。

作者目录逐项深读

整数集合的实现

四级证据 1/6。 intset以连续有序数组保存整数,encoding决定每个元素宽度,length记录元素个数而不是字节数。本节点用“整数集合的实现”作观察点,执行rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证整数集合的实现时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

升级

四级证据 2/6。 新值超出当前编码时创建更宽解释并从尾向头搬迁旧元素,避免原地覆盖未读取数据。本节点用“升级”作观察点,执行rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证升级时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

升级的好处

四级证据 3/6。 统一最小宽度让查找保持有序二分,并在小整数集合上减少对象与指针开销。本节点用“升级的好处”作观察点,执行rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证升级的好处时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

降级

四级证据 4/6。 Redis 3.0整数集合只升级不降级,删除大值不会自动收窄编码,因此不能假设内存立即回落。本节点用“降级”作观察点,执行rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证降级时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

整数集合API

四级证据 5/6。 intsetAdd、intsetRemove与intsetFind通过编码感知的读写函数访问元素,并返回是否发生实际变更。本节点用“整数集合API”作观察点,执行rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c或等价源码探针,保存版本、输入、前后状态和能推翻解释的反例。

验证整数集合API时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

重点回顾

四级证据 6/6。 第6章 整数集合的回顾要重新证明“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,并用同一输入比较结构前态、变更轨迹、故障首错与恢复后态

验证重点回顾时,先预测新值范围从“int32”切到“int64”会改变哪个字段、偏移、文件或消息;再固定插入位置做一次对照。若故障注入没有破坏“contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置”,就撤回当前解释而不是补写故事。

最小源码与运行切片

+git clone --branch 3.0 --depth 1 https://github.com/redis/redis.git redis-3.0
+cd redis-3.0
+rg 'intsetUpgradeAndAdd|intsetSearch' src/intset.c

该切片固定Redis 3.0分支、编译器、配置、数据集和命令序列;先保存结构或函数位置,再运行隔离实例。任何持久化损坏、断线、故障转移、大键或高流量实验都必须使用临时数据并规定CPU、内存、磁盘、延迟和停止上限。

unit: rdi-06-integer-set
source_file: intset.c
axis_a: "新值范围"
axis_b: "插入位置"
fault: "升级后按旧宽度解释contents,或假设删除会自动降级"
invariant: "contents按当前编码解释且严格有序,升级后所有旧值保持数值不变,新值落在正确位置"
replay: same_version_same_input

三个必须主动触发的误区

误区 1

现象 → 混入超大整数 原因 → 全集合升级内存翻倍 修法 → 按值域分集合存储

误区 2

现象 → 对 intset 做大量随机删除 原因 → 数组搬移成本高 修法 → 考虑换哈希编码或批量重建

误区 3

现象 → 以为整数集合有序就全能 原因 → 只支持整数类型 修法 → 非整数元素自动换编码

小结

  • 整数集合是有序无重复紧凑数组
  • 类型升级机制节省内存
  • 插入触发升级保证有序
  • 只存整数且元素不多时使用
  • 升级之后不会降级

练习、答案与节点验证

练习

问题 1: 整数集合的升级机制如何工作?

问题 2: 为什么升级后不允许降级?

问题 3: 判断:集合 65536 应使用什么编码,内存占用如何估算?(独立实现)

术语复核与本章回顾

完成第6章 整数集合意味着能从intset.c解释理解intset的有序连续存储、编码升级、重排插入和不支持降级的空间权衡,能运行章专属状态实验,能制造反例并在复位后证明旧状态没有残留。

资料与写作方式声明

本章以黄健宏《Redis设计与实现》(机械工业出版社)权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…