模块的管理

在了解模块之前,我们必须学习如何编译模块、载入模块以及卸载模 块,本节将会对这些内容进行介绍。

编译模块

虽然不同模块的编译方法各有不同,但绝大多数模块都会在文档中详 细地说明自身的编译方法,用户只需要按照文档里提示的方法进行编 译即可。

比如,为了方便用户尝试模块功能,Redis在自身的源码中附带了几个 测试用途的模块,这些模块位于源码的/src/modules文件夹中:

$ pwd
/Users/huangz/redis/src/modules
$ ls
Makefile helloblock.c helloblock.xo hellotimer.c hellotype.so helloworld.c hellow
orld.xo testmodule.so
gendoc.rb helloblock.so hellocluster.c hellotype.c hellotype.xo helloworld.so testmo
dule.c testmodule.xo

其中以.c结尾的C程序文件就是模块的源码,而以.so结尾的就是已经 编译完毕的模块,也就是常见的C共享库文件。一般来说,这些测试模 块都会随着Redis服务器一并被编译,但如果情况不是这样的,用户也 可以随时通过执行make命令来编译这些模块,就像这样:

$ make
cc -I. -W -Wall -dynamic -fno-common -g -ggdb -std=c99 -O2 -fPIC -c helloworld.c -
o helloworld.xo
ld -o helloworld.so helloworld.xo -bundle -undefined dynamic_lookup -lc
ld: warning: -macosx_version_min not specified, assuming 10.11
ld: warning: object file (helloworld.xo) was built for newer OSX version (10.13) than being
linked (10.11)
# 省略部分编译信息
cc -I. -W -Wall -dynamic -fno-common -g -ggdb -std=c99 -O2 -fPIC -c hellotimer.c -
o hellotimer.xo
ld -o hellotimer.so hellotimer.xo -bundle -undefined dynamic_lookup -lc
ld: warning: -macosx_version_min not specified, assuming 10.11
ld: warning: object file (hellotimer.xo) was built for newer OSX version (10.13) than being
linked (10.11)

载入模块

为了使用指定的模块,用户可以在服务器启动时,通过给定 loadmodule选项来指定想要载入的模块:

loadmodule <module_path>

loadmodule选项接受模块的具体文件路径作为参数。

举个例子,如果用户想要载入位于文件路径 /Users/huangz/redis/src/modules/helloworld.so 的模块,就需要使用以下选项:

loadmodule /Users/huangz/redis/src/modules/helloworld.so

用户除了可以在服务器启动时使用loadmodule选项载入模块之外,还 可以在Redis服务器运行期间,执行MODULE LOAD命令来在线载入模 块,被载入的模块将立即生效并可用:

MODULE LOAD module_path

与loadmodule配置选项一样,MODULE LOAD命令也接受模块的文件路径 作为参数。作为例子,用户可以通过执行以下MODULE LOAD命令来载入 上述helloworld.so文件中的模块:

redis> MODULE LOAD /Users/huangz/redis/src/modules/helloworld.so
OK

服务器在成功载入模块之后会返回OK作为结果,这时用户就可以执行 模块中的各项功能了。如果模块载入失败,那么MODULE LOAD命令将返 回一个错误:

redis> MODULE LOAD /not/exists/module.so
(error) ERR Error loading the extension. Please check the server logs.

一条loadmodule指令或者一条MODULE LOAD命令只能载入一个模块,如 果用户想要载入多个模块,就需要使用多条loadmodule指令或者执行 多个MODULE LOAD命令,就像这样:

MODULE LOAD /path/to/module_a.so
MODULE LOAD /path/to/module_b.so
MODULE LOAD /path/to/module_c.so

其他信息

  • 复杂度:O(1)。

  • 版本要求:MODULE LOAD命令从Redis 4.0版本开始可用。

列出已载入的模块

用户可以通过执行MODULE LIST命令来查看服务器目前已载入的所有模块:

redis> MODULE LIST
1) 1) "name" --"name"字段的值记录了模块的名字
2) "test" --这个模块名为"test"
3) "ver" --"ver"字段的值记录了模块的版本号
4) (integer) 1 --这个模块的版本号为1
2) 1) "name"
2) "helloworld" --这个模块名为"helloworld"
3) "ver"
4) (integer) 1 --这个模块的版本号为1

多个模块的信息将以嵌套数组的形式给出,顶层数组中的每个数组项 都记录了一个模块的信息,而子数组中的各个数组项则以“字段-值” 的形式记录了模块的各项具体信息。

其他信息

  • 复杂度:O(N),其中N为服务器已载入的模块数量。

  • 版本要求:MODULE LIST命令从Redis 4.0版本开始可用。

卸载模块

当用户不再需要使用某个模块的时候,可以执行MODULE UNLOAD命令来 卸载指定的模块,被卸载的模块将立即失效并不再可用(除非用户再 次载入该模块):

MODULE UNLOAD module_name

注意,与MODULE LOAD命令不一样,MODULE UNLOAD命令接受的参数是 模块的名字,而不是模块的文件路径或者模块的文件名。

比如,如果用户曾经使用以下命令来载入名为HELLOWORLD的模块:

redis> MODULE LOAD /Users/huangz/redis/src/modules/helloworld.so
OK

那么它就需要使用模块的名字HELLOWORLD来调用MODULE UNLOAD命令, 以此来卸载该模块:

redis> MODULE UNLOAD HELLOWORLD
OK

尝试使用模块的文件路径或者模块的文件名去调用MODULE UNLOAD命 令,都会得到一个错误:

redis> MODULE UNLOAD /Users/huangz/redis/src/modules/helloworld.so
(error) ERR Error unloading module: no such module with that name
redis> MODULE UNLOAD helloworld.so
(error) ERR Error unloading module: no such module with that name

一般来说,模块文件的前缀名都会和模块的名字保持一致,比如上文 中的helloworld.so模块文件注册的就是名为HELLOWORLD的模块。如果 用户不确定模块名,可以使用17.1.3节介绍的MODULE LIST命令查看。

其他信息

  • 复杂度:O(1)。

  • 版本要求:MODULE UNLOAD命令从Redis 4.0版本开始可用。