Redis(十八)——底层数据结构(三)

IntSet(整数集合)

IntSet ​ 是Redis中Set类型 的一种紧凑型内存编码格式,专门用于存储纯整数的小型集合。

复制代码
// Redis 7.0 源码 intset.h
typedef struct intset {
    uint32_t encoding;  // 编码方式:INTSET_ENC_INT16/32/64
    uint32_t length;    // 元素个数
    int8_t contents[];  // 柔性数组,存储实际数据
} intset;

intset结构:
+------------+--------+-------------------+
|  encoding  | length |    contents[]     |
|  (4字节)   | (4字节)|   (可变长度)      |
+------------+--------+-------------------+
                 ↓
实际存储(INTSET_ENC_INT16,存储[1, 2, 3]):
+------------+--------+----+----+----+
|    INT16   |   3    | 1  | 2  | 3  |
|   (0x0002) | (0x0003)|0x01|0x02|0x03|
+------------+--------+----+----+----+
内存占用:4 + 4 + 3 * 2 = 14字节

这个其实和ziplist有点类似,都是连续的内存空间,只是intset只能存整数,而且也只是set的底层结构,没有尾指针,元素中也没有前一个元素的大小,就一个很普通的数组。去重就很简单了,使用二分查找现在的数组中有没有,没有就插入有就不插入了。没错intset是有序的,但是set类型是无序的,无序是set的api体现的,这里就不拆解了哦。如果inset是无序的那么每次增删改查都可能需要全数组遍历,虽然是连续内存但是性能消耗同样很大。

IntSet与Hashtable特性对比

特性 IntSet(整数集合) Hashtable(哈希表)
存储类型 只存整数 任意类型
内存占用 极低(紧凑数组) 较高(指针+entry结构)
查找性能 O(log n) 二分查找 O(1) 平均,O(n) 最坏情况
插入性能 O(n) 需要移动元素 O(1) 平均
删除性能 O(n) 需要移动元素 O(1) 平均
最大元素数 可配置(默认512) 无限制
自动转换 超限或非整数 → hashtable 不会转回intset

Radix Tree(基数树)

Radix Tree (基数树/压缩前缀树)是一种优化的前缀树(Trie),用于高效存储和查找字符串集合。Redis 5.0+ 将其用于Stream类型的底层实现以及Cluster节点配置。

复制代码
// Redis中的Rax(Radix Tree实现)
typedef struct rax {
    raxNode *head;      // 根节点
    uint64_t numele;    // 元素数量
    uint64_t numnodes;  // 节点数量
} rax;

typedef struct raxNode {
    uint32_t iskey:1;     // 是否包含key
    uint32_t isnull:1;    // 关联值是否为NULL
    uint32_t iscompr:1;   // 是否压缩节点
    uint32_t size:29;     // 子节点数量或压缩字符串长度
    unsigned char data[]; // 柔性数组存储数据
} raxNode;

普通前缀树:               Radix树(压缩后):
       r                        r
      / \                      / \
     o   u                  oot  un
    /     \                /       \
   o       n             (ot)      (n)
  /         \           /   \       \
 t*          n*       key1  key2    key3
  ↓           ↓
"root"      "run"

存储: root, rooster, run
压缩节点: "oot", "un"

其实和普通的前缀树的区别就是,假如一个父节点只有一个子节点,那么就把他们两个合并,

https://ivanzz1001.github.io/records/post/data-structure/2018/11/18/ds-radix-tree

这个文章写的非常的清楚,比主包现在讲要好很多,大家可以去看看吧。

Redis 10大数据类型底层结构总结

以下是整理后的Redis数据类型底层结构对比表格:

数据类型 底层结构版本说明 主要特性 使用场景
String 1. SDS (Simple Dynamic String)<br>2. int (整数编码)<br>3. embstr (嵌入式字符串)<br>4. raw (原始SDS) O(1)获取长度,二进制安全 缓存、计数器、session
List 1. quicklist (3.2+)<br>2. ziplist (旧版)<br>3. linkedlist (旧版) 双向遍历,支持阻塞操作 消息队列、最新列表
Hash 1. listpack (7.0+)<br>2. ziplist (7.0前)<br>3. hashtable 字段值映射,适合存储对象 对象存储、商品属性
Set 1. intset (整数集合)<br>2. hashtable 无序唯一集合,支持去重操作 标签、好友关系
ZSet 1. listpack (7.0+)<br>2. ziplist (7.0前)<br>3. skiplist+dict 有序集合,按分数排序,范围查询 排行榜、延迟队列
Stream Radix Tree (基数树) 消息持久化,支持消费者组 消息队列、日志流
Bitmap String (SDS) 位操作,节省空间 用户签到、活跃统计
HyperLogLog 1. sparse (稀疏)<br>2. dense (密集) 固定内存,基数估算误差0.81% UV统计、去重计数
GEO Sorted Set (底层: ziplist/listpack或skiplist+dict) 地理计算,支持半径查询 附近的人、地理位置
Bitfield String (SDS) 位操作,原子性 标志位、紧凑存储

总结

本篇主要总结和介绍intset、radix tree。

相关推荐
Season45014 分钟前
Redis命令 (generic即通用命令)
数据库·redis·bootstrap
liwulin05061 小时前
【ollama】自定义结构化输出
linux·前端·数据库·ollama
木易士心1 小时前
MyBatis数据源切换全面解析
数据库
新中地GIS开发老师1 小时前
地信职业百科④:GIS开发工程师
前端·数据库·gis·webgis·三维gis开发
云和恩墨2 小时前
从“第二存储”到多智能体协作,云和恩墨充实数据基础设施产品矩阵
数据库
ClouGence2 小时前
SAP HANA 到 Doris 数据迁移:4 种方案对比与迁移教程
数据库·后端·dba
霸道流氓气质2 小时前
ApiPost 中配置自动获取 Token 并调用业务接口完整指南
java·服务器·数据库
我不想名字重复2 小时前
redis缓存和数据库数据保持一致
数据库·redis·缓存
时空无限2 小时前
vllm 大模型启动缓存相关环境变量 export
linux·缓存·vllm
宇宙第一小趴菜2 小时前
三、Oracle 核心原理
数据库·oracle