1. 前言:
在第一章节我们了解到了,redis底层所涉及的数据结构,但是这并非是离我们最近的一层,在此之上,redis实现了一层对象与我们交互。我们在本篇内容中将了解到:
- 对象对应的实现
- redis一些常用特性的实现
2.对象:
2.1:对象的基本结构:
redis 在通常建立存储一个内容的同时会建立两个对象,一个为key(通常为字符串),一个为value(可以为任何类型的对象)。
type
指的是对象的类型,redis中有五种类型。
类型常量 | 对象名称 |
---|---|
REDIS_STRING | 字符串对象 |
REDIS_LIST | 列表对象 |
REDIS_HASH | 哈希对象 |
REDIS_SET | 集合对象 |
REDIS_ZSET | 有序集合对象 |
encoding
指的是底层数据结构
编码常量 | 数据结构 |
---|---|
REDIS_ENCODING_INT | long类型整数 |
REDIS_ENCODING_EMSTR | embstr编码的简单动态字符串 |
REDIS_ENCODING_RAR | 简单动态字符串 |
REDIS_ENCODING_HT | 字典 |
REDIS_ENCODING_INKEDLIST | 双端链表 |
REDIS_ENCODING_ZIPLIST | 压缩列表 |
REDIS_ENCODING_INTSET | 整数集合 |
REDIS_ENCODING_SKIPLIST | 跳跃表和字典 |
当然,type和encoding不能随意组合。可组合列表如下。
类型 | 编码 | 对象 |
---|---|---|
REDIS_STRING | REDIS_ENCODING_INT | 整数实现的字符串对象 |
REDIS_STRING | REDIS_ENCODING_EMSTR | embstr编码的简单动态字符串对象 |
REDIS_STRING | REDIS_ENCODING_RAR | 简单动态字符串组成的动态字符串对象 |
REDIS_LIST | REDIS_ENCODING_ZIPLIST | 压缩列表实现的列表对象 |
REDIS_LIS | REDIS_ENCODINGLINKEDLIST | 双端链表实现的列表对象 |
REDIS_HASH | REDIS_ENCODINGLINKEDLIST | 压缩列表实现的哈希对象 |
REDIS_HASH | REDIS_ENDODING_HT | 字典实现的哈希对象 |
REDIS_SET | REDIS_ENCODING_INSET | 使用整数集合实现的集合对象 |
REDIS_SET | REDIS_ENCODING_SET | 使用字典实现的集合对象 |
REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的有序集合对象 |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 使用跳跃表和字典实现的有序集合对象 |
ptr
指向底层实现的数据结构。
2.2:字符串对象:
字符串对象的编码可以是int,raw和embstr。
-
embstr: 小于32位,用于存储短的字符串,并且不提供变更的方法,如果存在修改总会变成raw格式。
-
long:用于存储整数,当在long范围内的整数通常用long格式编码;long追加字符串总会变为 raw 编码。
-
raw:用于存储长的字符串
- raw 创建释放对象对内存的操作为两次,与sdshdr内存不连续
- embstr 创建释放对象对内存操作的次数为1次,内存连续
2.3:列表对象:
列表对象的底层可以是压缩列表和链表
- 压缩列表的列表的数据结构
- 双端链表的列表的数据结构
编码使用的条件
- 如果列表对象保存的所有字符串的长度都小于64字节且元素数量小于512个,则使用压缩列表。
- 反之,则使用双端链表。
2.4:哈希对象:
哈希对象的底层实现可以是压缩列表和字典。
- 当使用压缩列表
- 使用压缩列表作为底层数据结构的时候,元素从尾部添加。
- 在添加key-value时,压缩列表会把key先放入尾部,然后吧value放入尾部。
- 当使用字典
编码使用的条件
- 如果列表对象保存的所有字符串的长度都小于64字节且元素数量小于512个,则使用压缩列表。
- 反之,则使用字典。
2.5:set集合对象:
集合对象可以使用 inset 和 ht 字典实现,
编码使用的条件
- 如果列表对象保存的所有字符串的长度都小于64字节且元素数量小于512个,则使用intset。
- 反之,则使用字典。
2.6. 有序集合对象
有序集合对象的底层可以是压缩列表和跳表。
- 当使用压缩列表
- 存储思路和哈希对象类似,依旧是 value score 并列放置,不过内部是有序的。小元素在前,大元素在后。
- 插入的时候一般使用插入排序,如果插入的元素最大,则时间复杂度最小,因为不需要挪动元素。
- 使用跳表+字典
有序集合在使用这两种组合结构是为链各个目标。
- 能O(1)查询时间分值
- 能通过分值快速筛序成员
编码使用的条件 - 如果列表对象保存的所有字符串的长度都小于64字节且元素数量小于128个,则使用intset。
- 反之,则使用字典。