对象和编码
Redis并没有直接采用底层数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象、有序集合对象这五种不同类型的对象。
Redis在执行命令之前首先会根据对象的类型来判断一个对象是否可以执行给定的命令。然后再根据编码类型选择具体的底层实现。
适用对象的好处是:可以针对不同的适用场景,为对象设置不同的数据结构底层实现,以优化对象在不同场景下的使用效率
对象的类型与编码
Redis使用Redis的对象RedisObject来表示数据库中的键和值,当我们使用Redis执行操作的时候一定会创建两个对象,其中一个对象用作键值对的键,另一个对象用作键值对的值。其中每个对象的数据结构由类型常量和类型编码共同决定
首先通过type属性找到对象的类型
类型常量 | 对象的名称 |
---|---|
REDIS_STRING | 字符串对象 |
REDIS_LIST | 列表对象 |
REDIS_HASH | 哈希对象 |
REDIS_SET | 集合对象 |
REDIS_ZSET | 有序集合对象 |
然后通过encoding确定底层具体实现
1.字符串
类型 | 编码 | 对象 |
---|---|---|
REDIS_STRING | REDIS_ENCODING_INT | 使用整数值实现的字符串对象 |
REDIS_STRING | REDIS_ENCODING_EMBSTR | 使用embstr编码的简单动态字符串实现的字符串对象 |
REDIS_STRING | REDIS_ENCODING_RAW | 使用简单动态字符串实现的字符串对象 |
- int编码:如果对象是一个long类型
- embstr编码:对象小于等于44字节(连续空间,申请和释放都只需要一次)
- raw编码:对象大于44字节
2.列表
类型 | 编码 | 对象 |
---|---|---|
REDIS_LIST | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的列表对象 |
REDIS_LIST | REDIS_ENCODING_LINKEDLIST | 使用双端链表实现的列表对象 |
使用压缩列表的条件:同时满足
- 列表对象保存的所有字符串元素的长度都小于64字节
- 列表对象保存的元素数量小于512个
3.哈希
类型 | 编码 | 对象 |
---|---|---|
REDIS_HASH | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的哈希对象 |
REDIS_HASH | REDIS_ENCODING_HT | 使用字典实现的哈希对象 |
使用压缩列表的条件:同时满足
- 哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
- 哈希对象保存的键值对数量小于512个
4.集合
类型 | 编码 | 对象 |
---|---|---|
REDIS_SET | REDIS_ENCODING_INSERT | 使用整数集合实现的集合对象 |
REDIS_SET | REDIS_ENCODING_HT | 使用字典实现的集合对象 |
使用整数数组的条件:同时满足
- 集合对象内所有元素都是整数值
- 集合对象保存的元素数量不超过512个
5.有序集合
类型 | 编码 | 对象 |
---|---|---|
REDIS_ZSET | REDIS_ENCODING_ZIPLIST | 使用压缩列表实现的有序集合对象 |
REDIS_ZSET | REDIS_ENCODING_SKIPLIST | 使用跳跃表和字典实现的有序集合对象 |
使用压缩列表的条件:同时满足
- 有序集合保存的所有元素成员的长度都小于64字节
- 有序集合保存元素的数量小于128个
重点回顾
- Redis数据库中的每个键值对的键和值都是一个对象
- Redis共有字符串、列表、哈希、集合、有序集合五种类型的对象,每种类型的对象至少都有两种或以上的编码方式,不同的编码可以在不同的使用场景上优化对象的使用效率
- 服务器在执行某些命令之前,会先检查给定键的类型能否执行指定的命令,而检查一个键的类型就是检查键的值对象的类型
- Redis的对象系统带有引用计数实现的内存回收机制,当一个对象不再被使用时,该对象所占用的内存就会被自动释放
- Redis会共享值为0到9999的字符串对象
- 对象会记录自己的最后一次被访问的时间,这个时间可以用于计算对象的空转时间