Redis的五种数据类型:
- 字符串(string)
- 列表(list)
- 哈希(hash)
- 集合(set)
- 有序集合(zset)
Redis所用到的底层数据结构:
- long类型的整数
- 简单动态字符串(sds)
- emb编码的简单动态字符串(embstr)
- 链表(实际是双端链表 linkedlist)
- 字典(实际是哈希表 hashtable)
- 整数集合(intset)
- 压缩列表(ziplist)
- 跳跃表(skiplist)
对象系统
redis并没有直接使用以上的数据结构来实现键值对数据库,而是基础这些数据结构创建了一个对象系统,包含:字符串对象、列表对象、哈希对象、集合对象和有序集合对象,这些对象都至少用到了一种数据结构。
使用对象的优点:
- 针对不同的使用场景,为对象设置不同的数据结构实现,从而优化对象在不同场景下的使用效率
- Redis的对象系统实现了基于引用计数技术的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会自动释放
- Redis还基引用计数技术实现了对象共享机制,在适当的条件下,通过让多个数据库键共享同一个对象来节约内存
- Redis的对象带有访问时间的记录信息,该信息可以用于计算数据库键的空转时长,在服务器启用了maxmemory功能的情况下,空转时长较大的那些键可能会优先被服务器删除
对象的类型和编码
一个键值对会至少创建两个对象:键对象、值对象
如set a “a”命令,会创建两个字符串对象,redis中的每个对象由一个redisObject结构表示:
typedef struct redisObject{
unsigned type:4; //类型
unsigned encoding 4; //编码
void * ptr; //指向底层实现数据结构的指针
......
}robj;
对象类型:
所有的键的对象类型都是字符串对象,使用type命令可以查看一个键值对的值对象类型:
编码和底层实现:
对象的ptr指针指向对象的底层数据结构,这些数据结构由encoding(编码)属性决定,下图为对象的编码表:
每种类型的对象都至少使用的两种不同的编码,可以通过如下命令查看对象所使用的编码:
下图列出了每种对象可以使用的编码:
下图为不同的编码的对象所对应的object encoding 命令输出值:
同一种数据类型的redis可以有多种底层实现数据结构,极大地提升了reids的灵活性和效率,下面列出不同的对象类型,以及相同的对象类型不同的值的情况下所对应的底层数据结构。
字符串对象
字符串对象可以使用的编码有:int、raw、embstr
- 当值时为大于32字节的字符串时,使用raw
- 当值为整数,并且这个整数可以用long类型来表示时,使用int
- 当值时为小于等于32字节的字符串时,使用embstr
embstr编码是专门用于保存短字符串的一种编码方式。
列表对象
列表对象的编码可以是ziplist或者linkedlist
- 列表对象保存的所有字符串元素长度小于64字节并且元素数量小于
512个时,使用ziplist编码 - 否则使用linkedlist编码
ziplist编码:
linkedlist编码:
哈希对象
哈希对象的编码可以是ziplist或者hashtable
- 哈希对象保存的所有键值对的键和值的字符串长度小于64字节并且键值对数量小于
512个时,使用ziplist编码 - 否则使用hashtable编码
ziplist编码:
压缩列表:
hashtable编码:
集合对象
集合对象的编码可以是intset或者hashtable
- 集合对象保存的所有元素是整数值并且元素个数不超过512个,用intset编码
- 否则使用hashtable编码
intset编码:
hashtable编码:
有序集合对象
有序集合对象的编码可以是ziplist或者skiplist
- 有序集合保存的元素个数小于128并且元素采用长度小于64字节时,用ziplist编码
- 否则使用skiplist编码
ziplist编码:
skiplist编码: