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。

相关推荐
好记忆不如烂笔头abc2 小时前
oracle日志生成量
数据库·oracle
无盐海2 小时前
Redis 集群模式Redis Cluster
数据库·redis·缓存
醉风塘2 小时前
数据库索引深度解析:从数据结构到最佳实践
数据结构·数据库
Austindatabases2 小时前
OceanBase SeekDB SQL优化案例---MySQL在客户端会没有市场的
数据库·sql·mysql·adb·oceanbase
刘个Java2 小时前
手搓遥控器通过上云api执行航线
java·redis·spring cloud·docker
好大哥呀2 小时前
Redis解析
数据库·redis·缓存
User_芊芊君子2 小时前
GLM-4.7 与 MiniMax M2.1 实测上线免费使用:国产大模型的 “工程化 + 长周期” 双赛道落地
数据库·redis·缓存
JELEE.2 小时前
redis笔记(python、Django怎么配置使用redis)
redis·笔记·python
IvorySQL2 小时前
Postgres 18 默认开启数据校验及升级应对方案
数据库·人工智能·postgresql·开源