Redis modules make possible the extension of Redis functionality using
external modules, by creating new Redis commands with performance and
features similar to what can be done inside the core itself.
The modules documentation is composed of the following files:
Redis modules are dynamic libraries loaded into Redis at startup or
using the `MODULE LOAD` command. Redis exports a C API, in the
* `INTRO.md` (this file). An overview about Redis Modules system and API. It's a good idea to start your reading here.
* `API.md` is generated from module.c top comments of RedisMoule functions. It is a good reference in order to understand how each function works.
* `TYPES.md` covers the implementation of native data types into modules.
* `BLOCK.md` shows how to write blocking commands that will not reply immediately, but will block the client, without blocking the Redis server, and will provide a reply whenever will be possible.
Redis modules make possible to extend Redis functionality using external
modules, implementing new Redis commands at a speed and with features
similar to what can be done inside the core itself.
Redis modules are dynamic libraries, that can be loaded into Redis at
startup or using the `MODULE LOAD` command. Redis exports a C API, in the
form of a single C header file called `redismodule.h`. Modules are meant
to be written in C, or any language with C binding functionality
like C++.
to be written in C, however it will be possible to use C++ or other languages
that have C binding functionalities.
Modules are Redis-version agnostic: a given module does not need to be
designed, or recompiled, in order to run with a specific version of
Redis. In addition, they are registered using a specific Redis modules
API version. The current API version is "1".
Modules are designed in order to be loaded into different versions of Redis,
so a given module does not need to be designed, or recompiled, in order to
run with a specific version of Redis. For this reason, the module will
register to the Redis core using a specific API version. The current API
version is "1".
This document describes the alpha version of Redis modules. API,
functionality and other details may change in the future.
This document is about an alpha version of Redis modules. API, functionalities
and other details may change in the future.
# Loading modules
In order to test a new Redis module, use the following `redis.conf`
configuration directive:
In order to test the module you are developing, you can load the module
using the following `redis.conf`configuration directive:
loadmodule /path/to/mymodule.so
Load a module at runtime with the following command:
It is also possible to load a module at runtime using the following command:
MODULE LOAD /path/to/mymodule.so
To list all loaded modules, use:
In order to list all loaded modules, use:
MODULE LIST
Finally, unload (or reload) a module using the following command:
Finally, you can unload (and later reload if you wish) a module using the
following command:
MODULE UNLOAD mymodule
Note that `mymodule` is the name the module used to register itself
with the Redis core, and **is not** the filename without the
`.so` suffix. The name can be obtained using `MODULE LIST`. It is
recommended to use the same filename for the dynamic library and module.
Note that `mymodule` above is not the filename without the `.so` suffix, but
instead, the name the module used to register itself into the Redis core.
The name can be obtained using `MODULE LIST`. However it is good practice
that the filename of the dynamic library is the same as the name the module
uses to register itself into the Redis core.
# A Hello World module
# The simplest module you can write
In order illustrate the basic components of a module, the following
implements a command that outputs a random number.
In order to show the different parts of a module, here we'll show a very
simple module that implements a command that outputs a random number.
#include "redismodule.h"
#include<stdlib.h>
@ -56,7 +66,7 @@ implements a command that outputs a random number.
return REDISMODULE_OK;
}
int RedisModule_OnLoad(RedisModuleCtx *ctx) {
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1)
== REDISMODULE_ERR) return REDISMODULE_ERR;
@ -68,17 +78,21 @@ implements a command that outputs a random number.
}
The example module has two functions. One implements a command called
`HELLOWORLD.RAND`. This function is specific to that module. In
addition, `RedisModule_OnLoad()` must be present in each Redis module.
It is the entry point for module initialization, and registers its
commands and other private data structures.
In order to avoid namespace collisions, module commands should use the
dot-notation, for example, `HELLOWORLD.RAND`.
Namespace collisions will cause `RedisModule_CreateCommand` to fail in
one or more modules. Loading will abort and an error condition
returned.
HELLOWORLD.RAND. This function is specific of that module. However the
other function called `RedisModule_OnLoad()` must be present in each
Redis module. It is the entry point for the module to be initialized,
register its commands, and potentially other private data structures
it uses.
Note that it is a good idea for modules to call commands with the
name of the module followed by a dot, and finally the command name,
like in the case of `HELLOWORLD.RAND`. This way it is less likely to
have collisions.
Note that if different modules have colliding commands, they'll not be
able to work in Redis at the same time, since the function
`RedisModule_CreateCommand` will fail in one of the modules, so the module
loading will abort returning an error condition.
# Module initialization
@ -89,9 +103,9 @@ The following is the function prototype:
int RedisModule_Init(RedisModuleCtx *ctx, const char *modulename,
int module_version, int api_version);
The `Init` function announces to the Redis core that the module has a
given name, its version (reported by `MODULE LIST`), and that it uses
a specific version of the API.
The `Init` function announces the Redis core that the module has a given
name, its version (that is reported by `MODULE LIST`), and that is willing
to use a specific version of the API.
If the API version is wrong, the name is already taken, or there are other
similar errors, the function will return `REDISMODULE_ERR`, and the module
@ -100,15 +114,15 @@ similar errors, the function will return `REDISMODULE_ERR`, and the module
Before the `Init` function is called, no other API function can be called,
otherwise the module will segfault and the Redis instance will crash.
The second function called, `RedisModule_CreateCommand`, registers
commands with the Redis core. The following is the prototype:
The second function called, `RedisModule_CreateCommand`, is used in order
to register commands into the Redis core. The following is the prototype:
int RedisModule_CreateCommand(RedisModuleCtx *ctx, const char *cmdname,
RedisModuleCmdFunc cmdfunc);
Most Redis modules API calls have the `context` of the module
as first argument, in order to reference the calling module's context
and the client executing a given command.
As you can see, most Redis modules API calls all take as first argument
the `context` of the module, so that they have a reference to the module
calling it, to the command and client executing a given command, and so forth.
To create a new command, the above function needs the context, the command
name, and the function pointer of the function implementing the command,
@ -121,9 +135,9 @@ The command function arguments are just the context, that will be passed
to all the other API calls, the command argument vector, and total number
of arguments, as passed by the user.
The arguments are provided as pointers to a specific data type, the
`RedisModuleString`. This is an opaque data type with API functions
enabling access and use. Direct access to its fields is never needed.
As you can see, the arguments are provided as pointers to a specific data
type, the `RedisModuleString`. This is an opaque data type you have API
functions to access and use, direct access to its fields is never needed.
Zooming into the example command implementation, we can find another call:
@ -134,29 +148,52 @@ exactly like other Redis commands do, like for example `INCR` or `SCARD`.
# Setup and dependencies of a Redis module
Redis modules do not depend on Redis or 3rd party libraries, nor do they
Redis modules don't depend on Redis or some other library, nor they
need to be compiled with a specific `redismodule.h` file. In order
to create a new module, just copy a recent version of `redismodule.h`
in your source tree, link all the libraries you want, and create
a dynamic library and export the `RedisModule_OnLoad()` function symbol.
a dynamic library having the `RedisModule_OnLoad()` function symbol
exported.
The module will be able to load into different versions of Redis.
# Passing configuration parameters to Redis modules
When the module is loaded with the `MODULE LOAD` command, or using the
`loadmodule` directive in the `redis.conf` file, the user is able to pass
configuration parameters to the module by adding arguments after the module
file name:
loadmodule mymodule.so foo bar 1234
In the above example the strings `foo`, `bar` and `123` will be passed
to the module `OnLoad()` function in the `argv` argument as an array
of RedisModuleString pointers. The number of arguments passed is into `argc`.
The way you can access those strings will be explained in the rest of this
document. Normally the module will store the module configuration parameters
in some `static` global variable that can be accessed module wide, so that
the configuration can change the behavior of different commands.
# Working with RedisModuleString objects
The command argument vector `argv` passed to module commands, and the
return value of other module APIs functions, are of type `RedisModuleString`.
Most often Redis module strings are passed directly to other API calls.
However, a number of API functions enable direct access to the string
object. For example,
Usually you directly pass module strings to other API calls, however sometimes
you may need to directly access the string object.
There are a few functions in order to work with string objects:
@ -248,15 +289,13 @@ This is the full list of format specifiers:
* **v** -- Array of RedisModuleString objects.
* **!** -- This modifier just tells the function to replicate the command to slaves and AOF. It is ignored from the point of view of arguments parsing.
The function returns either a `RedisModuleCallReply` object on success,
or NULL on error.
The function returns a `RedisModuleCallReply` object on success, on
error NULL is returned.
NULL is returned when the command name is invalid, the format specifier
uses characters that are not recognized, or when the command is called
with the wrong number of arguments. In the above cases the `errno` var
is set to `EINVAL`. NULL is also returned when, in an instance with
Cluster enabled, the target keys are non local hash slots. In this
case `errno` is set to `EPERM`.
NULL is returned when the command name is invalid, the format specifier uses
characters that are not recognized, or when the command is called with the
wrong number of arguments. In the above cases the `errno` var is set to `EINVAL`. NULL is also returned when, in an instance with Cluster enabled, the target
keys are about non local hash slots. In this case `errno` is set to `EPERM`.
Another common use case for this feature is iterating over the arrays of
some collection and only returning the ones passing some kind of filtering.
It is possible to have multiple nested arrays with a postponed reply.
It is possible to have multiple nested arrays with postponed reply.
Each call to `SetArray()` will set the length of the latest corresponding
call to `ReplyWithArray()`:
@ -444,7 +484,8 @@ This creates a 100 items array having as last element a 10 items array.
# Arity and type checks
Often commands need to check that the number of arguments and type of the key
is correct. To report a wrong arity, use `RedisModule_WrongArity()`:
is correct. In order to report a wrong arity, there is a specific function
called `RedisModule_WrongArity()`. The usage is trivial:
if (argc != 2) return RedisModule_WrongArity(ctx);
@ -466,8 +507,8 @@ is of the expected type, or if it's empty.
## Low level access to keys
Low level access to keys enable operations on value objects associated
with keys directly, with a speed similar to what Redis uses internally to
Low level access to keys allow to perform operations on value objects associated
to keys directly, with a speed similar to what Redis uses internally to
implement the built-in commands.
Once a key is opened, a key pointer is returned that will be used with all the
@ -477,44 +518,39 @@ associated value.
Because the API is meant to be very fast, it cannot do too many run-time
checks, so the user must be aware of certain rules to follow:
* Opening the same key multiple times where at least one instance is
opened for writing, is undefined and may lead to crashes.
* While a key is open, it should only be accessed via the low level key
API. For example opening a key, then calling DEL on the same key using
the `RedisModule_Call()` API will result in a crash. However it is safe
to open a key, perform some operation with the low level API, close it,
then use other APIs to manage the same key, and later opening it again
to do some more work.
In order to open a key the `RedisModule_OpenKey` function is used. It
returns a key pointer, used in subsequent calls to access and modify
* Opening the same key multiple times where at least one instance is opened for writing, is undefined and may lead to crashes.
* While a key is open, it should only be accessed via the low level key API. For example opening a key, then calling DEL on the same key using the `RedisModule_Call()` API will result into a crash. However it is safe to open a key, perform some operation with the low level API, closing it, then using other APIs to manage the same key, and later opening it again to do some more work.
In order to open a key the `RedisModule_OpenKey` function is used. It returns
a key pointer, that we'll use with all the next calls to access and modify