Redis07-对象结构体redisObject

Redis是一个key-value型数据库,key只能是字符串,value可以是字符串、列表、集合、有序集合和散列表,这5种数据类型用结构体robj表示,我们称之为Redis对象。

#define LRU_BITS 24
typedef struct redisObject {
    
    
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS;  //缓存淘汰使用
    int refcount;           //引用计数
    void *ptr;
} robj;

redisObject的type字段表示具体的数据类型,如下

#define OBJ_STRING 0
#define OBJ_LIST 1
#define OBJ_SET 2
#define OBJ_ZSET 3
#define OBJ_HASH 4

redisObject的encoding字段表示具体当前对象底层存储采用的数据结构

type类型 encoding类型 备注
OBJ_STRING raw,int,embstr raw与embstr都是sds
OBJ_LIST quicklist
OBJ_SET dict,intset
OBJ_ZSET dict,ziplist
OBJ_HASH ziplist,skiplist+dict

raw与embstr区别
redisObject的ptr字段是void*类型的指针,指向实际存储的某一种数据结构,但是当redisObject存储的数据可以用long类型表示时,数据直接存储在ptr字段。可以看出,为了创建一个字符串对象,必须分配两次内存,redisObject与sds存储空间;两次内存分配效率低下,且数据分离存储降低了计算机高速缓存的效率。因此提出OBJ_ENCODING_EMBSTR(embstr)编码的字符串,当字符串内容比较短时,只分配一次内存,robj与sds连续存储,以此提升内存分配效率与数据访问效率。

redisObject的refcount存储当前对象的引用次数,用于实现对象的共享。共享对象时,refcount加1;删除对象时,refcount减1,当refcount值为0时释放对象空间。删除对象的代码如下:

void decrRefCount(robj *o) {
    
    
    if (o-refcount == 1) {
    
    
        switch(o-type) {
    
     //根据对象类型,释放其指向数据结构空间
        case OBJ_STRING: freeStringObject(o); break;
        case OBJ_LIST: freeListObject(o); break;
        case OBJ_SET: freeSetObject(o); break;
        …………
        }
        zfree(o); //释放对象空间
    } else {
    
    
        //引用计数减1
        if (o-refcount != OBJ_SHARED_REFCOUNT) o-refcount--;  
    }
}

robj的refcountlru字段占24比特,用于实现缓存淘汰策略,可以在配置文件中使用maxmemory-policy配置已用内存达到最大内存限制时的缓存淘汰策略。lru根据用户配置的缓存淘汰策略存储不同数据,常用的策略就是LRU与LFU。LRU的核心思想是,如果数据最近被访问过,那么将来被访问的几率也更高,此时lru字段存储的是对象访问时间;LFU的核心思想是,如果数据过去被访问多次,那么将来被访问的频率也更高,此时lru字段存储的是上次访问时间与访问次数。

猜你喜欢

转载自blog.csdn.net/u011624903/article/details/111147298