redis中的robj结构体对象

1.对象结构体robj

typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;
} robj;

熟悉redis的都知道。redis是一个k-v型的数据库。其中key只能是字符串。但value可以是字符串,列表,集合,有序集合的哈希。

这五种类型在redis中被称为对象结构体robi。

server.h/506:

/* The actual Redis Object */
#define OBJ_STRING 0    /* String object. */
#define OBJ_LIST 1      /* List object. */
#define OBJ_SET 2       /* Set object. */
#define OBJ_ZSET 3      /* Sorted set object. */
#define OBJ_HASH 4      /* Hash object. */
以上五种代表的是type。
 
并且,针对某一类的对象,redis有可能采取不同的底层存储策略。
server.h/651:
/* 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 */ 数据结构:SDS。可存储的类型:字符串。
#define OBJ_ENCODING_INT 1     /* Encoded as integer */ 数据结构:整数。可存储的类型:字符串。
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */  数据类型:字典。可存储的类型:集合,hash,有序集合。
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */  压缩字典
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */未使用。
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */  压缩列表。hash,zset
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */  整数集合。set
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */  跳表。zset
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */  SDS。字符串
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */  快速列表。list
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */  stream。stream
以上的11种,代表了当前对象底层存储采用的数据结构。即encoding。
 
第一:对象在不同的情况下可能采取不同的数据结构存储。比如上的OBJ_ENCODING_INTSET 6和OBJ_ENCODING_HT 2。如果一个set中全是整型,那么就会用前者存储。如果在sadd是存了非整型,那么就会变为后者。
 
第二:同一对象,会采用不同的数据类型存储吗。从上面的举例不难看出,会的。并且实际占用的空间不会太多,因为存的都是指针。
举例:
typedef struct zset {
    dict *dict;
    zskiplist *zsl;
} zset;
zset实际上字典和跳表都有存储。
 
第三:SDS的OBJ_ENCODING_RAW和OBJ_ENCODING_EMBSTR有什么区别。
OBJ_ENCODING_EMBSTR主要是为了方便存储。如果robj存储的数据能用long类型表示,数据直接存储在ptr。不然的话,你存放一个sds,既要申请robj,又要申请sds,并且内存还不连续。效率是十分慢的。
然后整个数据在内存中对齐是这么的:

 

上面是robj,下面是sds。

lru存储的是和淘汰策略有关的数据。

搞16位存储的是该对象上次的访问时间。低8位存储的是该对象的访问次数。

posted @ 2022-07-11 23:45  拿什么救赎  阅读(118)  评论(0编辑  收藏  举报