RedisObject解析

413 阅读2分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

Redis的背景我们就不需要过多的进行介绍了,下面直入主题

Redis常用的5种数据类型:

String,List,Hash,Set,ZSet

下面我们直接给出结论 5种数据类型对应的地层结构为:

1.String

  • int(整数型)
  • raw(简单动态字符串SDS)
  • embstr(embstr编码的简单动态字符串)

2.List

ziplist(压缩列表) linkedlist(双端链表)

3.Hash

ziplist(压缩列表) hashtable(哈希表,字典)

4.Set

iniset(整数集合) hashtable(哈希表,字典)

5.ZSet

ziplist(压缩列表) skiplist(跳表)

redisObject

以上结构大家都很熟悉了,这次我们来说说Redis的对象:redisObject(robj)

Redis使用这么多种数据结构,那么Redis是如何管理和使用这些数据结构的呢,就是通过redisObject,首先我们来看下它的定义

redisObject的定义

typedef struct redisObject{
     
     unsigned type:4;     //类型
     
     unsigned encoding:4; //编码
     
     void *ptr;           //指向底层数据结构的指针
     
     int refcount;        //引用计数
     
     unsigned lru:22;     //记录最后一次被程序访问的时间
 
}robj

type属性记录了对象的类型,他对应的取值就是redis的5种数据类型

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

encoding属性记录了编码方式,也就是对应了实际的底层数据结构

/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 * is set to one of this fields for this object. */
#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */

ptr则是指向真正数据的数据指针。如一个string类型,ptr可能指向一个sds,如一个hash类型,ptr则可能指向一个ziplist或是一个hashtable

refcount属性是该对象被应用的次数,被引用一次,数值+1,当引用技术为0时,则会被释放 我们来看下相应的代码

void incrRefCount(robj *o) {
    o->refcount++;
}

void decrRefCount(robj *o) {
    if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
    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;
            case OBJ_ZSET: freeZsetObject(o); break;
            case OBJ_HASH: freeHashObject(o); break;

            default: serverPanic("Unknown object type"); break;
        }
        zfree(o);
    } else {
        o->refcount--;
    }
}

lru熟悉用来标记对象的空转时长,如果服务器打开了maxmemory的选项,如果服务器超出了内存上线,会根据这个属性进行内存释放

多态

有了redisObject之后, 在执行处理数据类型的命令时, 进行类型检查和对编码进行多态操作就简单得多了.

如针对一个hash类型执行hset操作,那么执行流程如下:

未命名文件.png

以上我们大概了解了Redis组织对象的方式:redisObject redisObject管理着Redis底层的多种数据结构