redis源码解析(七):对象

引言

redis每一个键,都是一个redisObject对象,对象里面存放特定的数据结构用来保存值。之前讲过redis内部有五种数据结构:sds字符串、双向链表、字典、压缩列表、整数集合,跳跃表等redis的对象系统使用这五个数据结构构建了五种对象分别是:字符串对象、列表对象、哈希表对象、集合对象以及有序集合对象。

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;

type属性

/* Object types */
// 对象类型
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4

encoding属性

每个type属性可以有多种不同的实现方式,这样子做的好处在于可以根据不同的使用场景来为一个对象设置不同的底层结构,从而优化对象在某一个场景的使用效率。redis五种对象能够通过以下编码实现:

redis源码解析(七):对象_第1张图片

// 对象编码
#define REDIS_ENCODING_RAW 0     /* Raw representation */
#define REDIS_ENCODING_INT 1     /* Encoded as integer */
#define REDIS_ENCODING_HT 2      /* Encoded as hash table */
#define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
#define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define REDIS_ENCODING_EMBSTR 8  /* Embedded sds string encoding */

ptr属性

该属性用来保存redis存储的值,例如type属性为REDIS_SET ,encoding属性为REDIS_ENCODING_HT ,那么该ptr属性内部保存的就是一个哈希表结构。

refcount属性

该属性的作用与智能指针相类似,用一个int类型的数值保存redis对象指向的目标被引用的次数,程序可以通过跟踪对象的引用信息,在适当的时候自动释放对象并回收内存。其工作模式如下:
1.在创建一个新对象时,引用计数的值会被初始化为1
2.当对象被一个新程序引用时,他的引用计数值会被增1
3.当对象不再被一个程序使用时,他的引用计数值回被减1
4.当对象引用计数值为0时,对象占用的内存会被释放

该属性功能是能够共享需要被多次使用的对象,减少内存的消耗。
redis源码解析(七):对象_第2张图片
但在这里说明一下,redis只能共享int类型的字符串对象并且只有双端链表、字典、跳跃表、sds字符串能够使用共享对象,而压缩列表和整数集合不能使用共享对象。redis初始化的时候系统会自动生成0到9999的字符串对象,以便共享。至于为什么不能共享字符串的原因如下:
每次共享对象前需要检查共享对象和目标对象是否完全相同因此,
1.如果共享对象是保存字符串对象,那么验证操作的复杂度为 O(1)
2.共享对象是保存字符串值的字符串其验证操作复杂度为O(N)
3.如果共享对象包含了多个字符串值(哈希表、双端链表、跳跃表)则验证的复杂度会达到O(N^2)
虽然共享对象可以节约内存,但是受到cpu时间的限制,redis只能对包含整数值的字符串对象进行共享。

LRU属性

LRU属性记录了对象的空转时长,也就是该对象上次被访问距现在的时间,当redis存储的数据超过限制,则会优先释放空转时间较长的对象。

你可能感兴趣的:(redis,缓存,数据库)