redis对象有5种类型(type),8种编码格式(encoding),8种编码格式都有对应的数据结构。
对象类型:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081308383-392156217.jpg)
编码格式:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081318407-1263681886.jpg)
有11种组合方式:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081252378-656871176.jpg)
五种类型的编码选择:
1. 字符串类型
int:全部为数值类型。
embstr:长度小于32字节的字符串。
raw:长度大于32字节的字符串。
2. 列表对象类型
以下条件下用压缩列表ziplist实现:
* 列表对象字符长度都小于64字节。
* 元素个数小于512个。
其他情况用双向列表linkedlist实现。
3. 哈希对象类型
以下条件下用压缩列表ziplist实现:
* 列表对象字符长度都小于64字节。
* 元素个数小于512个。
其他情况用字典ht实现。
4. 集合对象类型
以下条件下用整数集合intset实现:
* 列表对象都是整数对象。
* 元素个数小于512个。
其他情况用跳跃表skiplist实现。
5. 有序集合对象类型
以下条件下用压缩列表ziplist实现:
* 列表对象长度小于64字节。
* 元素个数小于128个。
其他情况同时用字典ht和跳跃表skiplist实现。
注释:
用字典是为了便于o(1)复杂度查询某个元素,用跳跃表是为了便于范围查询。
## 1. sds
数据结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081257374-1947630287.jpg)
总结:
* 便于存储特殊字符,二进制安全。
* 高效查询字符长度,复杂度O(1)。
* 惰性空间分配,减少扩容,缩容次数。
* 防止数组溢出。
* \0结尾,可以延用部分C语言函数库。
## 2. 链表
节点结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081259372-579311049.jpg)
链表结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081326374-931192470.jpg)
总结:
* 双向无环链表。
## 3. 整数集合
数据结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081317351-1780643721.jpg)
总结:
* 保存有序,不重复的整数集合。
* 数据类型由encoding决定,可以存储16位,32位,64位整数,尽可能的节省内存。
* 只支持类型升级,不支持降级。
## 4. 字典
字典结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081251374-1987573203.jpg)
hash表结构:
![](media/15669854457609/15670632214239.jpg)
节点结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081316356-1035070817.jpg)
总结:
* 字典底层用两个hash表实现,h[0]在平时使用,h[1]在rehash的过程中用到。
* rehash使用渐进式rehash,将任务均摊。rehash过程中,insert操作只在h[1]中,delete,select,update操作可能会对两个表同时操作。
* hash表用链地址法解决hash冲突。
* hash值使用murmurhash2算法实现,可以获得比较散列的hash值。
## 5. 跳跃表
跳跃表模型:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081300378-181437102.jpg)
节点结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081330373-1874962746.jpg)
总结:
* 每个节点的层高由随机函数生成(1~32),每落在每层的概率相差两倍。
* 每个节点的分值可以相等,节点对象唯一。
* 节点按分值排序,当分值相等时,按对象排序。
## 6. 压缩列表
压缩列表结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081250417-1334483689.jpg)
各节点结构:
![](https://img2018.cnblogs.com/blog/916824/201909/916824-20190905081322374-281369416.jpg)
总结:
* content字节数<254 previous_entry_length用1个字节;content字节数>=254 previous_entry_length用5个字节。
* encoding 前两位表示编码,00,01,11表示数组类型,长度分别为1字节,2字节,5字节,11表示整数类型。后面位数存content长度。
* zlbytes 整个压缩列表字节数
* zltail 起始地址到entryN的偏移量,便于找到尾部节点。
* zllen 节点个数,当个数>65535时需遍历整个列表获取节点个数。
* zlend 特殊标志0xff 表示结尾。
* 节点新增,或者节点删除都可能导致连锁更新,但出现概率不高。