redis 4.0 扩展模块介绍(官网文章翻译)

Redis 模块介绍

  Redis外部模块是用来扩展 Redis功能的,我们可以实现一个与Redis原生命令速度和特性类似的命令在Redis内核中。Redis modules 实际是一个动态库,它能够让Redis-cli 使用 MODULE LOAD 命令去把它加载到Redis内核。Redis module 使用 C 的API实现的,相应的函数在redismodule.h头文件中,这也叫意味着RedisModule 必须使用 c或者c++这种去实现它。
  Redis Module 不依赖于Redis的版本,只要相应Redis 版本支持模块加载即可。所以如果有个新Redis版本出现了,之前的模块不用重新编译和设计就可以被加载到新的版本中。这都归功于Redis Module 使用了一个特殊的API version来在Redis内部进行注册,当前API version 是 1.

加载模块
加载模块方法
  • 方法1 在redis.conf 中增加 loadmodule /path/to/mymodule.so
  • 方法2 使用MODULE LOAD /path/mymodule.so 命令去加载
读取模块列表命令
  • MODULE LIST
卸载模块命令
  • MODULE UNLOAD mymodule
    模块的动态库的命名应该和模块一个名字这是一个很好的习惯
module demo

为了能更好的展示一个模块的不同组成部分,在本文将实现一个返回一个随机数的命令的模块

#include "redismodule.h"
#include <stdlib.h>

int HelloworldRand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModule_ReplyWithLongLong(ctx,rand());
    return REDISMODULE_OK;
}

MODULE LOAD   ./xxx.so  1 2 3 4 5  .so 后面的才是参数
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1)
        == REDISMODULE_ERR) return REDISMODULE_ERR;

    if (RedisModule_CreateCommand(ctx,"helloworld.rand",
        HelloworldRand_RedisCommand) == REDISMODULE_ERR)
        return REDISMODULE_ERR;

    return REDISMODULE_OK;
}

上面的俩个函数,第一个函数是我们自定义命令(模块)的一个函数,第二个函数是RedisModule_Onload是一个必须出现在每个Redis module中的一个函数,这个函数里面要对一个指向redis module 的一个指针进行初始化,并且对其注册命令、可能被使用到的私有结构体。
注意我们给一个命令的命名风格是 module.command 。这样就不太可能出现命令重名的情况,如果不同的模块有相同命名的命令Redis会报错,因为一个 RedisModule_CreateCommand 函数将会在其中一个模块的创建命令的过程中失败,所以模块加载将会返回 REDISMODULE_ERR 的错误码

Module 初始化
RedisModule_Init
int RedisModule_Init(RedisModuleCtx *ctx, const char *modulename,int module_version, int api_version);

上面这个函数应该是在OnLoad函数中第一个被调用的,它用来告诉Redis内核我们要注册的module的module_name 、module_version、api_version,如果这个api不是第一个调用的直接调用其他api会出现core dump
如果有API版本错误、模块name已存在、其他类似的错误话,这个函数将返回REDISMODULE_ERR,并且在OnLoad函数中必须把这个错误返回出去。
注意如果这个函数不是第一个调用的那么会发生段错误导致redis崩溃。

RedisModule_CreateCommand

这个函数用来注册一个命令在Redis内核中

int RedisModule_CreateCommand (RedisModuleCtx *ctx, const char *name, RedisModuleCmdFunc 
cmdfunc, const char *strflags, int firstkey, int lastkey, int keystep)

正如你所看到的,大多数Redis 模块调用的API都有第一个参数 context ,以至于对创建命令、执行命令的时候都需要一个这样的参数。
第二个参数指的是命令名字
第三个参数是一个具体命令实现的函数指针
第四个参数是flag 标志,它由以下多个或者一个构成,当多个构成的时候中间以空格为分隔符。

  • “write” 它表示这个命令也行会修改数据
  • “readonly” 它表示这个函数只会从读取数据,但是不会修改数据
  • “admin” 表示管理命令,使用这个参数表示在实现的命令函数中也许会做replication(同步)之类的操作
  • “deny-oom” 表示也许会使用一些额外的内存但在内存不足的时候不会再强行阻塞式申请
  • “deny-script” 不允许这个 module 命令使用到Lua脚本中
  • “allow-loading” 允许这个命令当redis-server在加载数据的时候允许,只有该命令不会与Redis内部的数据交互的时候才可以使用这个module 命令,如果不了解这个选项千万别用
  • “pubsub” 这个选项表这个命令会发出一些东西在 Pub/Sub 管道
  • “random” 这个选项表该命令有不同的输出即使有相同的参数
  • “allow-stable” The command is allowed to run on slaves that don’t serve stale data. Don’t use if you don’t know what this means.
  • “no-monitor” Don’t propoagate the command on monitor. Use this if the command has sensible data among the arguments.
  • “fast” 这个命令的时间复杂度不会高于 logN ,N是遍历元素的个数

为了在上面讲的 ctx中创建一个命令,我们需要一个ctx、命令名、函数指针。这个函数指针的类型是RedisModuleCmdFunc

RedisModuleCmdFunc

该函数的第一个参数也是ctx,它将被相应的其他API调用它时传递,其他的俩个命令行参数由用户传递。就像下面的原型所展示的出的,第二个参数类型是一个特殊的string的数组。对于这个RedisModuleString来讲,它是一个特殊的数据类型,我们只能通过API去访问、使用它,绝对不能直接去访问或者修改它的内容。

int RedisModuleCmdFunc(RedisModuleCtx * ctx ,RedisModuleString ** argv, int argc);

回顾到上面初始化命令时的Load函数中,还有一个RedisModule_ReplyWithLongLong函数,该函数只是返回一个整形给调用这个命令的client,事实上其他Redis命令也是这个原理,比如 INCR or SCARD

传递配置参数给Redis module

当一个Redis module被MODULE LOAD 命令加载时或使用 loadmodule 直接在redis.conf文件中加载时,用户是能够传递配置参数给相应的模

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值