1. Redis模块简介
Redis Modules System是4.0出现一大改动点,使得可以通过外部模块对Redis进行功能性扩展。
2. Redis添加自定义模块
Redis的模块采用的是动态链接库的方式,可以启动的时候加载,也可以在运行时加载(MODULE LOAD),在Linux系统里面,可以通过dlopen,dlsym等实现动态加载库,在业务系统里面,经常用于将业务代码和框架代码进行分离,以实现插件化开发。在Redis里面也是同样的道理。要实现分离,首先需要的是初始化,以便让框架可以找到对应的方法,这就需要进行注册,Redis通过RedisModule_Init方法进行注册模块,和RedisModule_CreateCommand注册自定义方法。Redis进行模块化,可以扩大Redis的生态圈,满足一些扩展性功能需求,现在就有一个Hub用于收集Redis模块的插件。如:http://redismodules.com/
使用Redis模块的步骤如下:
(1)下载并安装好 redis 4.0 以上的版本
(2)新建一个目录并包含 redismodule.h 文件,里面包含了 redis 相关的操作的函数和变量的声明。
(3)编写相关的业务代码:rand_test.c
/* redis命令的回调函数 */
int HelloworldRand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
RedisModule_ReplyWithLongLong(ctx, rand());
return REDISMODULE_OK;
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
{
/* 注册module */
if (RedisModule_Init(ctx, "hellworld", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)
{
return REDISMODULE_ERR;
}
/* 注册redis命令 */
if (RedisModule_CreateCommand(ctx, "helloworld.rand", HelloworldRand_RedisCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR)
{
return REDISMODULE_ERR;
}
return REDISMODULE_OK;
}
RedisModule_OnLoad 函数是 redis module 必须的函数,在这个函数中需要注册module和注册命令:
- RedisModule_Init 是用来注册 module 的函数,其参数包含一个ctx(上下文,用来向其他模块传递参数用的)、模块名字、该模块的版本号、redisModule的api版本。
- RedisModule_CreateCommand用来注册一个命令,也就是我们常用的set、get 等命令。其参数包含一个 ctx、命令名字、命令的回调函数、命令的类型(只读、写、读写等)、第一个key参数(The first argument that's a key (0 = no keys)),最后一个key参数(The last argument that's a key)、最后一个key和第一个key的距离。
(4)编译成 .so 动态库文件
gcc rand_test.c -fPIC -shared -o rand_test.so
(5)加载进 redis,有三种方法都可以加载:
-
在 redis.conf 文件中加入
loadmodule /path/to/rand_test.so
-
在服务器启动时加载
redis-server --loadmodule /path/to/rand_test.so
-
在启动的 client 中输入
module load /path/to/rand_test.so
(6)测试新加的命令,这里选择客户端加载模块
$ ./redis-cli
127.0.0.1:6379> MODULE LOAD path/to/rand_test.so
OK
127.0.0.1:6379> helloworld.rand
(integer) 23432432
127.0.0.1:6379>
3. Redis中安装布隆过滤器
(1)载redisbloom插件(redis官网下载即可):https://github.com/RedisLabsModules/redisbloom/
(2)解压并安装,生成.so文件
$ cd redisbloom-1.1.1/
$ make
(3)在redis配置文件(redis.conf)中加入该模块即可
loadmodule /path/to/rebloom.so
(4)启动redis
$ redis-server redis.conf
(5)测试是否安装成功
127.0.0.1:6379> bf.add users user2
(integer) 1
127.0.0.1:6379> bf.exists users user2
(integer) 1
127.0.0.1:6379> bf.exists users user3
(integer) 0
4. Redis模块的实现
redis模块的实现是通过调用操作系统的dlopen()、dlsys()、dlclose()这几个函数实现的,这几个函数的定义如下:
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
(1)dlopen() : 以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程,flag为打开模式,dlopen打开模式如下:
- RTLD_LAZY 暂缓决定,等有需要时再解出符号
- RTLD_NOW 立即决定,返回前解除所有未决定的符号
(2)dlsym() : 通过句柄和连接符名称获取函数名或者变量名;
(3)dlerror() : 返回出现的错误;
(4)dlclose() : 卸载打开的库;
参考:https://redis.io/topics/modules-intro