MST

星途 面试题库

面试题:Redis模块机制中如何实现简单的数据结构扩展

假设你要在Redis中通过模块机制扩展一种新的数据结构,类似有序集合但具有额外的属性存储功能。请描述实现这一功能的大致步骤,包括模块初始化、数据结构定义、命令实现等方面。
11.4万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

1. 模块初始化

  1. 加载模块:在Redis启动时,通过redis-server --loadmodule path/to/your_module.so加载自定义模块。
  2. 模块定义:在C语言代码中,使用RedisModule_ContextRedisModule_Symbol等结构和函数定义模块。例如:
#include "redismodule.h"
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (RedisModule_Init(ctx, "customsortedset", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
        return REDISMODULE_ERR;
    // 注册命令等操作
    return REDISMODULE_OK;
}

2. 数据结构定义

  1. 基础结构:可以基于Redis现有的有序集合数据结构(如zskiplist)进行扩展。例如,定义一个新的结构体:
typedef struct CustomSortedSet {
    zskiplist *zsl; // 有序集合部分
    // 额外属性存储,假设是一个哈希表存储属性名和属性值
    dict *properties; 
} CustomSortedSet;
  1. 内存管理:为新数据结构编写创建、释放等函数。例如:
CustomSortedSet* CreateCustomSortedSet() {
    CustomSortedSet *css = zmalloc(sizeof(CustomSortedSet));
    css->zsl = zslCreate();
    css->properties = dictCreate(&propertyDictType, NULL);
    return css;
}

void FreeCustomSortedSet(CustomSortedSet *css) {
    zslFree(css->zsl);
    dictRelease(css->properties);
    zfree(css);
}

3. 命令实现

  1. 注册命令:在模块初始化函数RedisModule_OnLoad中注册自定义命令。例如:
if (RedisModule_CreateCommand(ctx, "css.add", CustomSortedSetAddCommand,
    "write deny-oom", 1, 1, 1) == REDISMODULE_ERR)
    return REDISMODULE_ERR;
  1. 命令函数实现:以添加元素到自定义有序集合并设置属性为例:
int CustomSortedSetAddCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (argc < 4) {
        return RedisModule_WrongArity(ctx);
    }
    RedisModuleKey *key = RedisModule_OpenKey(ctx, argv[1], REDISMODULE_WRITE);
    if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
        CustomSortedSet *css = CreateCustomSortedSet();
        RedisModule_ModuleTypeSetValue(key, &customSortedSetType, css);
    } else if (RedisModule_KeyType(key) != REDISMODULE_KEYTYPE_MODULE) {
        return RedisModule_ReplyWithError(ctx, "WRONGTYPE Operation against a key holding the wrong kind of value");
    }
    CustomSortedSet *css = RedisModule_ModuleTypeGetValue(key);
    double score;
    if (RedisModule_StringToDouble(argv[2], &score) != REDISMODULE_OK) {
        return RedisModule_ReplyWithError(ctx, "Invalid score");
    }
    sds member = RedisModule_StringDMA(argv[3], NULL);
    zslInsert(css->zsl, score, member);
    // 设置额外属性,假设属性名在argv[4],属性值在argv[5]
    dictAdd(css->properties, sdsdup(argv[4]), sdsdup(argv[5]));
    RedisModule_CloseKey(key);
    return RedisModule_ReplyWithSimpleString(ctx, "OK");
}
  1. 其他命令:类似地实现获取元素、获取属性、删除元素等命令,根据具体需求操作自定义数据结构。

4. 模块类型定义

  1. 定义模块类型:创建一个RedisModuleType来管理自定义数据结构的生命周期和操作。
static RedisModuleType customSortedSetType;
void CustomSortedSetTypeRelease(RedisModuleTypeVal *val) {
    CustomSortedSet *css = val->ptr;
    FreeCustomSortedSet(css);
}
void CustomSortedSetTypeRegister(RedisModuleCtx *ctx) {
    RedisModuleTypeMethods methods = {
      .version = REDISMODULE_TYPE_METHOD_VERSION,
      .release = CustomSortedSetTypeRelease
    };
    customSortedSetType = RedisModule_CreateDataType(ctx, "customsortedset", &methods);
}
  1. 在模块初始化中注册类型:在RedisModule_OnLoad函数中调用CustomSortedSetTypeRegister(ctx)注册模块类型。