对象
Redis并没有直接用上面的几种数据结构实现kv数据库,而是将他们组合成为不同对象。Key对象与value对象。
对象的数据结构定义如下:(zset为有序集合)
下面是对象类型与实现的关系:
字符串对象——String
- 当为小于32位的整数时(因为ptr*是四个字节)存储为int
- 当为小于32字节的字符串时:embstr(浮点数也是保存为字符串)
- 当大于32字节时 raw
那么embstr和raw有啥区别呢?
- Embstr优化了,只需要一次分配,分配好obj和sds所用的内存
- 同上,释放内存也只需要释放一次~
- Obj和sds连续分配,所以加载一起加载,会比较快
此外,上面三种不同的string模式会在需要的时候自动互相转换,但注意embstr其实本质上是个只读的对象,对他的修改会先将它转换为raw
列表对象——List
LinkedList 或者 zipList,分别如下图所示(String对象是唯一可能被其他对象嵌套的对象)
这两种编码如何选择呢?
Ziplist:
1.每个元素的长度都小于64字节
2.元素的个数小于512个
其余都用linkedlist,上面条件有一个不满足则会选择转为linkedList
Hash对象
Ziplist或者hashtable(字典)
Ziplist键在前,值在后,从表尾开始插入。Hashtable则是将key和value都作为string对象
何时用ziplist
- 所有的键和值都小于64字节
- 数量小于512 个
转换情况同上。
Set对象
Intset 或者为hashtable(value为null)
何时用intset?
- 所有的元素都是整数值
- 元素个数不超过512个
转换情况同上
有序Set
Ziplist 或者为skipList+字典
为啥要用skipList+字典呢?
首先,skiplist和字典共享元素对象,所以不会发生浪费内存的情况,其次为了实现查找指定元素的值和查找某个范围的时间复杂度都比较小,所以采用两者结合
啥时候用ziplist?
- 元素数量小于128个
- 每个元素长度小于64字节
转换情况同上