我们需要一个数据类型符合自己的查询但是Redis本身不支持,此时,我们之前学习的这些数据类型就无法满足需求了。那么,自定义的数据类型是一个很好的解决方法
Redis 的基本对象结构
RedisObject 内部包括 type、encoding、lru、refcount 四个元数据以及一个 *ptr 指针
- type : 表示值类型,涵盖基本 5 大类型
- encoding : 值的编码方式,表示实行基本类型的底层数据结构
- lru : 记录对象最后一次被访问的时间,用于淘汰过期数据
- refconut : 记录对象的引用计数
- *ptr : 指向数据的指针,通过该指针指向不同的数据类型
开发一个新数据类型
- 定义一个新数据类型底层结构、type、encoding 属性值
- 实现新数据类型的创建,释放函数和基本操作命令

定义一个新类型 NewTypeNode
定义新数据类型的底层结构
使用newtype.h 定义新类型结构,代码如下
struct NewTypeObject {
struct NewTypeNode *head;
size_t len;
}NewTypeObject;
其中 NewTypeNode 结构就是自定义的新类型底层结构,包含一个Long类型的value,保存实际数据;一个 *next 指针,指向下一个 NewTypeNode 结构
struct NewTypeNode {
long value;
struct NewTypeNode *next;
};
在RedisObject 的 type 属性中增加新类型的定义
定义在Redis中的 server.h 文件中,定义一个 OBJ_NEWTYPE 的宏指代NewTypeObject
#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_NEWTYPE 7
开发新类型的创建和释放函数
创建函数
robj *createNewTypeObject(void){
// 初始化内存机构
NewTypeObject *h = newtypeNew();
// RedisObject 默认的创建函数
robj *o = createObject(OBJ_NEWTYPE,h);
return o;
}
初始化内存结构,通过使用zmalloc做底层的结构分配,Redis 默认会为每个数据结构定义一个默认的单独文件 t_newtype.c
NewTypeObject *newtypeNew(void){
NewTypeObject *n = zmalloc(sizeof(*n));
n->head = NULL;
n->len = 0;
return n;
}
createObject 是 Redis 本身提供的 RedisObject 创建函数,它的参数是数据类型的 type 和指向数据类型实现的指针*ptr
robj *createObject(int type, void *ptr) {
robj *o = zmalloc(sizeof(*o));
o->type = type;
o->ptr = ptr;
...
return o;
}
释放函数,是创建函数的反过程,使用 zfree 释放内存空间
开发新类型的命令操作
- 在 t_newtype.c 文件中增加命令操作的实现
void ntinsertCommand(client *c){
//基于客户端传递的参数,实现在NewTypeObject链表头插入元素
}
- 在 server.h 文件中,声明我们已经实现的命令,以便在 server.c 文件引用这个命令
void ntinsertCommand(client *c)
- 在 server.c 文件中的 redisCommandTable 里面,把新增命令和实现函数关联起来
struct redisCommand redisCommandTable[] = {
...
{"ntinsert",ntinsertCommand,2,"m",...}
}
