数据类型及其编码对应
1. 字符串对象 (String)
这是Redis最基础的类型。key都是字符串,其他复杂类型的元素也通常是字符串。
-
编码方式 (3种):
int: 当字符串内容可以被解析为一个64位有符号整数(long)时使用。- 优点: 极度节省内存,可以直接进行数值运算。
embstr: 当字符串长度小于等于44字节时使用。redisObject和sds头在内存中是连续分配的。- 优点: 创建和销毁时只需一次内存分配/释放,访问局部性好。
- 缺点: 只读。任何修改都会导致其转化为
raw编码。
raw: 当字符串长度大于44字节时使用。redisObject和sds头在内存中是分开分配的。- 优点: 可以动态修改和追加内容。
-
编码转换:
int->raw: 当值不再是整数或超出long范围时。embstr->raw: 任何修改操作都会触发此转换,无论修改后长度是否超过44字节。
2. 列表对象 (List)
有序的字符串列表,支持头尾插入。
- 编码方式 (1种):
quicklist: 这是Redis 3.2之后唯一的编码方式。它是一个双向链表,每个节点都是一个ziplist。- 优点: 结合了
ziplist的内存紧凑性和双向链表的灵活性,实现了空间和性能的完美平衡。 - 历史: 早期版本曾使用
ziplist和linkedlist,现已废弃。
- 优点: 结合了
3. 哈希对象 (Hash)
键值对的集合,类似于Java中的HashMap。
-
编码方式 (2种):
ziplist: 当哈希对象同时满足以下两个条件时使用:- 键值对数量小于512个。
- 所有键和值的字符串长度都小于64字节。
- 优点: 内存极其紧凑。键和值在
ziplist中相邻存储。
hashtable(底层为dict):不满足ziplist条件时使用。- 优点: 查找、插入、删除的时间复杂度为O(1),性能稳定。
-
编码转换:从
ziplist到hashtable的转换是单向的,一旦不满足ziplist的条件,就会转换,且不会再转回。
4. 集合对象 (Set)
无序、唯一的字符串集合。
-
编码方式 (2种):
intset: 当集合对象同时满足以下两个条件时使用:- 所有元素都是整数。
- 元素数量不超过512个。
- 优点: 专门为存储整数设计,内存效率极高。
hashtable(底层为dict):不满足intset条件时使用。- 实现方式: 元素作为
dict的key存储,value则全部设为NULL。 - 优点: 提供了O(1)复杂度的成员检查。
- 实现方式: 元素作为
-
编码转换:从
intset到hashtable是单向的。
5. 有序集合对象 (ZSet)
有序、唯一的字符串集合,每个元素关联一个score(分数)用于排序。
-
编码方式 (2种):
ziplist: 当有序集合同时满足以下两个条件时使用:- 元素数量小于128个。
- 所有元素的字符串长度都小于64字节。
- 实现方式:
ziplist中,元素和其score相邻存放,并保持有序。 - 优点: 内存占用小。
skiplist: 不满足ziplist条件时使用。- 实现方式: 这是一个复合结构,同时使用了
skiplist和dict。skiplist: 按照score对元素进行排序,支持高效的范围查询。dict: 存储元素到score的映射,支持O(1)复杂度的成员分数查找。
- 优点: 结合了两者的优势,既能快速查找,又能高效范围查询。
- 实现方式: 这是一个复合结构,同时使用了
-
编码转换:从
ziplist到skiplist是单向的。
总结表
| Redis对象 | 编码方式及条件 | 底层数据结构 | 核心优势 |
|---|---|---|---|
| String | int (整数值) / embstr (<=44字节) / raw (>44字节) |
long / 连续内存sds / 分离内存sds |
针对不同大小和类型的字符串进行内存优化 |
| List | quicklist (唯一) |
quicklist (双向链表 of ziplist) |
空间与性能的完美平衡 |
| Hash | ziplist (元素<512, 长度<64) / hashtable (其他) |
ziplist / dict |
小数据量时内存紧凑,大数据量时性能稳定 |
| Set | intset (全是整数, 数量<512) / hashtable (其他) |
intset / dict |
对纯整数集合进行极致内存优化 |
| ZSet | ziplist (元素<128, 长度<64) / skiplist (其他) |
ziplist / skiplist + dict |
结合跳表和字典,同时满足高效的范围查询和单点查询 |
注意:上述条件中的阈值(如512, 64, 128)均可通过Redis配置文件进行修改。