redis对象
本文对redis的对象进行概述,知识来源于《redis设计与实现》
我们可知,redis的用到的主要的数据结构有简单字符串(SDS)、双端链表、字典、压缩列表、整数集合等等。redis的对象都是由这些数据结构所实现。并且,redis可以对不同的对象在不同的使用场景下选择更加合适的数据结构实现。
此外,redis的对象系统还实现了基于引用计数技术的内存回收机制,并且,redis还通过使用引用计数实现了对象共享机制,这一机制可以在适当的条件下,通过让多个数据库键共享同一个对象来节约内存。
对象的类型与编码
对于redis来说,其中数据库保存的键值对的键总是一个字符串对象,值可以是redis中的任何对象(字符串对象、列表对象、哈希对象、集合对象或者有序集合对象)。
redis中的每个对象都是由一个redisObject结构表示:
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 指向底层实现数据结构的指针
void *ptr;
}
字符串对象
redis中的字符串对象分别有三种编码格式:int、raw、embstr
可知,在redis中,数值类型也是由字符串的形式进行存储,但是在这里又可以知道其(能用long类型表示的整数)存储的编码格式为int,如果是long double类型的数值则由raw或者embstr保存,具体不同如下分析:
![](https://img.haomeiwen.com/i19170123/4cae30ee80333ad8.png)
embstr:是专门用来保存短字符串的一种优化编码格式,该种编码和raw编码一样,都是使用redisObject结构和sdshdr结构来表示字符串对象。
但是作为一种优化编码格式,embstr在分配内存的时候,会分配一块连续的内存依次包含redisObject和sdshdr两个结构,相对于raw分别创建来说,embstr在分配内存和释放内存的时候都只要一次,而raw需要分别释放两个结构的内存,并且因为是一块内存,可以更好地利用缓存的优势。
列表对象
列表对象的编码可以是ziplist和linkedlist。
ziplist:使用压缩列表作为底层实现。
linkedlist:使用双端链表作为底层实现。
哈希对象
哈希对象的编码可以是ziplist和hashTable
ziplist:实现的哈希对象在保存新的键值对的时候,依次将保存键和值的两个压缩列表节点推入到压缩列表的表尾,这样就保证了键值对两个节点是紧紧挨在一起的,并且保证了键的节点在前,值的节点在后。
hashTable:键值对都是字符串对象
集合对象
集合对象的编码可以是intset或者hashTable
intset:使用整数集合作为底层实现,集合元素都是保存在整数集合中。
hashtable:每个键都为一个集合元素,键对应的值都为null。
有序集合
有序集合的编码可以是ziplist或者skiplist
ziplist:每个集合元素都是用两个紧挨着的压缩列表节点来保存,第一个节点保存元素的成员(member),第二个元素则保存元素的分值(score),且压缩列表内的集合函数按分值从小到大排序,分值小的放置在靠近表头的位置,而分值较大的元素放在靠近表尾的位置。
skiplist:使用zset结构作为作为底层实现。zset结构中同时包含了字典和一个跳跃表。
- skiplist将数据分别保存到字典和跳跃表中,即保存两份。
- 保存的两份的原因是,以字典的数据结构,能以0(1)的时间复杂度得到成员的分值。以跳跃表的数据结构,能更好地对集合进行范围型的操作。