redisObject
五种对象
- string(int + embstr sds+ raw sds)
- list(ziplist + linkedlist)
- hash(ziplist + dictht)
- set(intset + dictht)
- zset(ziplist + (skiplist+dictht))
Redis中每个对象都由redisObject结构表示,分别是type,encoding,ptr
typedef struct redisObject{
//类型,共5种
unsigned type:4;
//编码,即真正使用的数据结构
unsigned encoding:4;
//指针指向数据结构
void *ptr;
//引用计数
int refcount;
//最后一次被访问的时间
unsigned lru:22;
// 未使用的两个位
unsigned notused:2; /* Not used */
}robj;
type:5种 | REDIS_STRING:字符串 REDIS_LIST:列表 REDIS_HASH:哈希表 REDIS_SET:集合 REDIS_ZSET:有序集合 |
encoding:8种 | int:long类型整数 embstr:字符串 raw:字符串 ht:dictht字典 linkedlist:双端链表 ziplist:压缩链表 intset:整数集合 skiplist:跳跃表 |
string:3种 | int:普通整数 embstr:<=32字节的字符串 raw(sds):>32字节的字符串 |
list:2种 | ziplist:所有元素(StringObject)长度<64字节并且元素数量<512 linkedlist:不满足ziplist的条件 |
hash:2种 | ziplist:所有key和value长度<64字节并且键值对数量<512 dictht:不满足dictht |
set:2种 | intset:所有都是整数且数量<512 dictht:不满足intset |
zset:2种 | ziplist:所有元素长度<64字节且数量<128 skiplist+dictht:不满足ziplist |
1.string对象(int/ embstr/ raw)
(1) 整数用long类型表示
(2) >32字节的字符串用raw(sds)表示
(3)<=32字节的字符串用embstr(sds)表示
与raw的区别是:embstr的redisObject和sdshdr结构只调用了一次内存分配,内存是连续的。释放也只需要一次
而raw调用了两次内存分配,因此内存是不连续的。释放内存需要两次
embstr是只读的。
其他:
1.double类型的浮点数或者超出long范围的整数,会转化成sds来存储。
2.int和embstr都会转化成raw:整数类型如果append字符串会转成raw;embstr是只读的,如果修改也会变成raw。
2.list对象(ziplist/ linkedlist)
(1)ziplist
需要满足两个条件:所有字符串长度<64字节并且元素数量<512
每个列表元素用entry存储(如 1, three, 5)
(2)linkedlist
不满足ziplist的条件时会被转换成linkedlist
3.hash对象(ziplist/ dictht)
(1)ziplist
需要满足两个条件:所有key和value长度<64字节并且键值对数量<512
key和value紧挨好
(2)dictht
不满足ziplist会被转化成dictht
4.set对象(intset/ dictht)
(1)intset:整数
(2)dictht:字符串(key为字符串对象,value=null)
不满足intset时会被转换
5.zset对象(ziplist/ 跳表+dict)
(1)ziplist
第一个节点保存member,第二个节点保存score;score从小到大排序
(2)跳跃表+dict
跳跃表:主要用于范围型操作(ZRANK, ZRANGE)
dict:主要用于映射查找成员的score(ZCORE),复杂度O(1)
此外,同时用两个数据结构不会造成额外的空间浪费,因为都是通过指针来共享同一块内存区域