首页 redis中的数据对象
文章
取消

redis中的数据对象

这里取 redis5.0 版本的源码作为参考:

https://github.com/redis/redis/blob/5.0/src/server.h

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;

type

基础对象类型,包括字符串、列表、集合、有序集合、哈希,可选的值如下

/* 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. */

encoding

内部编码类型,不同的对象类型、不同的数据应用场景采用着不同的对象实现方式,也即编码,来达到最佳的性能和内存节约。

1
2
3
4
5
6
7
8
9
10
11
#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 /* No longer used: old list encoding. */
#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 */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */

基础对象和实现编码的关系:

基础对象类型实现编码
stringOBJ_ENCODING_INT、OBJ_ENCODING_EMBSTR、OBJ_ENCODING_RAW
listOBJ_ENCODING_ZIPLIST、OBJ_ENCODING_SKIPLIST、OBJ_ENCODING_QUICKLIST、OBJ_ENCODING_LINKEDLIST
setOBJ_ENCODING_INTSET、OBJ_ENCODING_HT
sorted setOBJ_ENCODING_ZIPLIST、OBJ_ENCODING_SKIPLIST
hashOBJ_ENCODING_HT、OBJ_ENCODING_ZIPLIST

lru

lru计时时钟

记录对象最后一次被访问(读写)的时间,当配置了 maxmemory 和 maxmemory-policy=volatile-lru 或 allkeys-lru 时,用于辅助 lru 算法删除键数据。

可通过以下方法查看键的空闲时间,单位为秒:

1
2
127.0.0.1:6379> object idletime demo
(integer) 22318

refcount

引用计数器。当为0时,可以安全回收当前对象空间。

1
2
127.0.0.1:6379> object refcount demo
(integer) 1

*ptr

数据指针,指向具体的数据对象,如 int、hashtable、embstr、ziplist 等。

下面拿一个 hash 的创建过程为例:

https://github.com/redis/redis/blob/5.0/src/object.c

robj *createObject(int type, void *ptr) {
    robj *o = zmalloc(sizeof(*o));
    o->type = type;  // 指定对象类型
    o->encoding = OBJ_ENCODING_RAW; // 默认指定编码为 OBJ_ENCODING_RAW
    o->ptr = ptr; // 数据指针指向数据
    o->refcount = 1; // 引用次数初始化为1

    /* Set the LRU to the current lruclock (minutes resolution), or
     * alternatively the LFU counter. */
    //设置 lru
    if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
        o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
    } else {
        o->lru = LRU_CLOCK();
    }
    return o;
}

robj *createHashObject(void) {
    unsigned char *zl = ziplistNew(); // 初始化一个空 ziplist
    robj *o = createObject(OBJ_HASH, zl); // 创建 redisObject
    o->encoding = OBJ_ENCODING_ZIPLIST; // 重定义 encoding 为 OBJ_ENCODING_ZIPLIST
    return o;
}
本文由作者按照 CC BY 4.0 进行授权