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。