这里取 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 */
基础对象和实现编码的关系:
基础对象类型 | 实现编码 |
---|---|
string | OBJ_ENCODING_INT、OBJ_ENCODING_EMBSTR、OBJ_ENCODING_RAW |
list | OBJ_ENCODING_ZIPLIST、OBJ_ENCODING_SKIPLIST、OBJ_ENCODING_QUICKLIST、 |
set | OBJ_ENCODING_INTSET、OBJ_ENCODING_HT |
sorted set | OBJ_ENCODING_ZIPLIST、OBJ_ENCODING_SKIPLIST |
hash | OBJ_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;
}