Redis对象 -- redisObject

Redis有主要以下数据结构,比如简单动态字符串、双端链表、字典、压缩列表、整数集合。

Redis没有直接用这些数据来直接实现键值对的数据库,而是在这些数据结构之上又包装了一层RedisObject(对象),RedisObject 有五种对象:字符串对象、列表对象、哈希对象、集合对象和有序集合对象。

typedef struct redisObject {

// 类型 unsigned type:4;

// 编码 unsigned encoding:4;

// 对象最后一次被访问的时间 unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */

// 引用计数 int refcount; // 指向实际值的指针 void *ptr;

} robj;

1.type类型:对于Redis键值对来说,键是一个字符串对象,而值可以是这五种对象的其中一种。

redis 配置里的ssl redists_Redis

2。ptr指针:指向对象的底层实现数据结构;

3.encoding:表示ptr指向的数据结构,就是对这个对象使用了什么数据结构作为底层实现。

redis 配置里的ssl redists_redis 配置里的ssl_02

redis 配置里的ssl redists_字符串_03

4.refcount

refcount表示引用计数,由于c语言不具备内存回收功能,所以Redis在自己的对象系统中添加了这个属性,当一个对象的引用计数为0时,则表示该对象已经不被任何对象引用,则可以进行垃圾回收了。扩展一下:Java中由于引用计数法解决不了循环引用的问题,所以 Java 中使用了可达性分析算法。那么 Redis 有没有考虑循环引用的问题呢?

5.lru表示对象最后一次被命令程序访问的时间。

五种对象对应的RedisObject

字符串对象(String)

字符串对象的encoding有三种分别是: int,raw,embstr。

1.如果一个字符串对象保存的是整数,并且这个整数可以用long类型标识,那么字符串对象会讲整数值保存在ptr属性中,并将encoding设置为int。加入有一个对象“10086”

redis 配置里的ssl redists_redis 配置里的ssl_04

2.如果一个字符串,并且字符串的长度大于32个字节,那么对象会使用一个简单动态字符串(SDS)来保存这个字符串,并将对象的编码设置为raw。字母的会使用一个Raw

redis 配置里的ssl redists_Redis_05

3.如果字符串保存的是一个字符串值,并且字符串长度小于等于32字节,那么字符串对象将使用embstr编码的方式来保存这个字符串。

redis 配置里的ssl redists_Redis_06

既然有了raw的编码方式,为什么还会有embstr编码方式呢?

因为embstr的编码方式有一些优点,如下:

  • embstr 编码将创建字符串对象所需的内存分配次数从 raw 编码的两次降低为一次。
  • 释放 embstr 编码的字符串对象只需要调用一次内存释放函数,而释放 raw 编码的字符串对象需要调用两次内存释放函数。
  • 因为 embstr 编码的字符串对象的所有数据都保存在一块连续的内存里面,所以这种编码的字符串对象比起 raw ,编码的字符串对象能够更好地利用缓存带来的优势。

哈希对象(hash)

哈希对象编码有两种,分别是:ziplist、hashtable。

当哈希对象保存的键值对数量小于512,并且所有键值对长度都小于64字节时,使用压缩列表;负责使用hashtable存储。

哈希对象的压缩列表对应的十一图如下:

redis 配置里的ssl redists_redis 配置里的ssl_07

哈希对象的 hashtable 对应的示意图如下

redis 配置里的ssl redists_数据结构_08

列表对象(list)

列表对象的编码有两种,分别是ziplist、linkedlist。

ziplist(压缩列表)主要是为节省内存而设计的内存结构,它的优点就是节省内存,但缺点就是比其他结构要消耗更多的时间,所以 Redis 在数据量小的时候使用压缩列表存储。

当列表的长度小于 512,并且所有元素的长度都小于 64 字节时,使用压缩列表存储;否则使用 linkedlist 存储。

压缩列表示意图:

redis 配置里的ssl redists_数据结构_09

列表对象链表示意图:

redis 配置里的ssl redists_字符串_10

集合对象(set)

集合对象的编码方式

String类型要存储一个 图片的id和图片的位置信息,比如要存储一个id为11110002234,位置信息为129394780011,这样一个信息,redisobject对象分配了8个字节,指针部分分配了8个字节,每一个图片地址有16字节,下来是32 字节,哈希表的每一项是一个dicEntry的结构体,用来指向一个键值对。dicEntry结构中有三个8字节的指针,分别指向key、value以及下一个dicEntry,三个指针共24字节。redis会申请32字节的空间。