redis使用对象系统来构建键值对数据库,这个对象系统包括:字符串对象,列表对象,哈希对象,集合对象和有序集合对象五种。
对象类型与编码
在redis中,每新建一个键值对,都会新建至少两个对象(一个为键,一个为值)。
redis对象定义如下:
typedef struct redisObject {
unsigned type:4; // 类型
unsigned encoding:4; // 编码
void *ptr; // 指向底层数据结构的指针
//...
} robj;
- 类型 redis的对象类型包括:
REDIS_STRING
,REDIS_LIST
,REDIS_HASH
,REDIS_SET
,REDIS_ZSET
。对于redis而言,键总是一个REDIS_STRING
,而值则可能是任意类型。redis中命令TYPE
是指值所对应的数据类型。 - 编码和底层实现
encoding
记录了对象所使用的编码,也就是使用了什么数据结构作为底层实现。
编码常量 | 对应数据结构 |
---|---|
REDIS_ENCODING_INT | long类型整数 |
REDIS_ENCODING_EMBSTR | embstr编码的简单动态字符串 |
REDIS_ENCODING_RAW | 简单动态字符串 |
REDIS_ENCODING_HT | 字典 |
REDIS_ENCODING_LINKEDLIST | 双端链表 |
REDIS_ENCODING_ZIPLIST | 压缩列表 |
REDIS_ENCODING_INTSET | 整数集合 |
REDIS_ENCODING_SKIPLIST | 跳表和字典 |
下图是类型,编码和对象的对应:
类型 | 编码 | 对象 |
---|---|---|
REDIS_STRING | REDIS_ENCODING_INT | 使用整数值实现的字符串对象 |
REDIS_STRING | REDIS_ENCODING_EMBSTR | 使用embstr编码的简单动态字符串实现的字符串对象 |
REDIS_STRING | REDIS_ENCODING_RAW | 使用简单动态字符串实现的字符串对象 |
REDIS_LIST | REDIS_ENCODING_LINKEDLIST | 使用双端链表实现的列表 |
REDIS_LIST | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的链表对象 |
REDIS_HASH | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的哈希对象 |
REDIS_HASH | REDIS_ENCODING_HT | 使用字典实现的哈希对象 |
REDIS_SET | REDIS_ENCODING_INTSET | 使用整数集合实现的集合对象 |
REDIS_SET | REDIS_ENCODING_HT | 使用字典实现的集合对象 |
REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的有序集合 |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 使用跳表和字典实现的有序集合 |
在redis中,可以使用OBJECT ENCODING
检查键的值对象编码。
字符串对象
字符串对象编码可以是int
,raw
,embstr
。
如果字符串可以保存为long类型,那么字符串对象的编码是int
。如果字符串长度不大于32字节,则使用embstr
编码保存。长度大于32字节的则使用raw
编码保存。
值 | 编码 |
---|---|
可以用long保存的整数 | int |
可以用long double保存的浮点数 | embstr或者raw(由长度决定) |
字符串值,或者大于long的整数以及大于long double的浮点数 | raw |
列表对象
列表对象编码可能是ziplist
或者linkedlist
。ziplist
编码的列表对象底层使用压缩列表实现,每个压缩列表节点(entry)保存一个列表元素。linkedlist
编码的列表对象底层使用双端列表实现,每个双端列表节点(node)都保存一个字符串对象,每个字符串对象保存一个列表元素。
值 | 编码 |
---|---|
列表对象所保存的字符串长度小于64byte,且列表内元素个数少于512 | ziplist |
其它情况下 | linkedlist |
哈希对象
哈希对象编码看是ziplist
或者hashtable
。
ziplist
编码的哈希对象使用压缩列表作为底层实现,键、值节点为压缩列表中相邻的两个节点。hashtable
编码的哈希对象使用字典作为底层实现,哈希对象中每个键值对都使用一个字典键值对来保存。
值 | 编码 |
---|---|
哈希对象所保存的键值对中键和值长度都小于64byte,且哈希内元素个数少于512 | ziplist |
其它情况下 | hashtable |
集合对象
集合对象编码可能是intset
或hashtable
。
intset
编码的集合对象底层使用整数集合实现。hashtable
编码的集合对象底层使用字典实现,字典值全是null。
值 | 编码 |
---|---|
集合对象保存的值全是整数,且集合内元素个数少于512 | intset |
其它情况下 | hashtable |
有序集合对象
有序集合对象编码可能是ziplist
或skiplist
。
ziplist
编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个相邻的压缩列表节点保存(一个保存元素,一个保存权值)。压缩列表内按权值排序。skiplist
编码的有序集合对象使用zset作为底层实现,一个zset同时包含一个字典和一个跳表。
typedef struct zset {
zskiplist *zsl;
dict *dict;
} zset;
其中跳表按分值排序保存元素,通过跳表可以方便的进行范围操作。字典则方便在O(1)时间内完成给定元素的权值查询。
值 | 编码 |
---|---|
有序集合元素长度均小于64byte,且有序元素个数小于128 | ziplist |
其它情况下 | skiplist |
网友评论