Redis modules extend the functionality of Redis by allowing developers to add custom commands and data types. This module will guide you through the process of creating your own Redis module, from setting up the development environment to writing and deploying your custom module.
- Setting Up the Development Environment
Before you start creating a custom Redis module, you need to set up your development environment.
Prerequisites
- Redis: Ensure you have Redis installed on your machine.
- C Compiler: Redis modules are typically written in C, so you need a C compiler like
gcc
. - Redis Module SDK: Download the Redis Module SDK from the Redis Labs GitHub repository.
Steps
-
Install Redis:
sudo apt-get update sudo apt-get install redis-server
-
Install GCC:
sudo apt-get install build-essential
-
Clone the Redis Module SDK:
git clone https://github.com/RedisLabs/redis-module-sdk.git cd redis-module-sdk
- Writing Your First Redis Module
Creating the Module File
Create a new file named mymodule.c
in the redis-module-sdk
directory.
Basic Structure of a Redis Module
Here is a basic structure of a Redis module:
#include "redismodule.h" // Function to be called when the command is executed int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc != 2) { return RedisModule_WrongArity(ctx); } RedisModule_ReplyWithString(ctx, argv[1]); return REDISMODULE_OK; } // Module initialization function int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (RedisModule_Init(ctx, "mymodule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } if (RedisModule_CreateCommand(ctx, "mymodule.mycommand", MyCommand_RedisCommand, "readonly", 1, 1, 1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } return REDISMODULE_OK; }
Explanation
- Include the Redis Module API:
#include "redismodule.h"
- Define the Command Function:
MyCommand_RedisCommand
is the function that will be executed when the custom command is called. - Initialize the Module:
RedisModule_OnLoad
is the entry point of the module. It registers the module and the custom command.
Compiling the Module
Compile the module using gcc
:
Replace /path/to/redis/src
with the path to the Redis source code.
- Loading and Testing the Module
Loading the Module
Start the Redis server with the module loaded:
Testing the Module
Open the Redis CLI and test the custom command:
- Advanced Module Features
Adding Custom Data Types
Redis modules can define custom data types. Here is an example of how to define a custom data type:
// Define the custom data type RedisModuleType *MyType; typedef struct { long long value; } MyTypeObject; // Function to create a new object void *MyType_RdbLoad(RedisModuleIO *rdb, int encver) { MyTypeObject *o = RedisModule_Alloc(sizeof(*o)); o->value = RedisModule_LoadSigned(rdb); return o; } // Function to save the object to RDB void MyType_RdbSave(RedisModuleIO *rdb, void *value) { MyTypeObject *o = value; RedisModule_SaveSigned(rdb, o->value); } // Function to free the object void MyType_Free(void *value) { RedisModule_Free(value); } // Module initialization function int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (RedisModule_Init(ctx, "mymodule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } // Register the custom data type RedisModuleTypeMethods tm = { .version = REDISMODULE_TYPE_METHOD_VERSION, .rdb_load = MyType_RdbLoad, .rdb_save = MyType_RdbSave, .aof_rewrite = NULL, .mem_usage = NULL, .digest = NULL, .free = MyType_Free }; MyType = RedisModule_CreateDataType(ctx, "mytype", 0, &tm); if (MyType == NULL) return REDISMODULE_ERR; return REDISMODULE_OK; }
Explanation
- Define the Custom Data Type:
MyTypeObject
is a simple structure with a singlevalue
field. - Implement RDB Load and Save Functions: These functions handle the serialization and deserialization of the custom data type.
- Register the Custom Data Type: The
RedisModule_CreateDataType
function registers the custom data type with Redis.
- Practical Exercise
Exercise
Create a Redis module that defines a custom command mymodule.add
which takes two integer arguments and returns their sum.
Solution
#include "redismodule.h" int AddCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (argc != 3) { return RedisModule_WrongArity(ctx); } long long a, b; if (RedisModule_StringToLongLong(argv[1], &a) != REDISMODULE_OK || RedisModule_StringToLongLong(argv[2], &b) != REDISMODULE_OK) { RedisModule_ReplyWithError(ctx, "ERR invalid integer"); return REDISMODULE_ERR; } RedisModule_ReplyWithLongLong(ctx, a + b); return REDISMODULE_OK; } int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { if (RedisModule_Init(ctx, "mymodule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } if (RedisModule_CreateCommand(ctx, "mymodule.add", AddCommand_RedisCommand, "readonly", 1, 1, 1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } return REDISMODULE_OK; }
Compiling and Testing
-
Compile the Module:
gcc -o mymodule.so -shared -fPIC mymodule.c -I/path/to/redis/src
-
Load the Module:
redis-server --loadmodule ./mymodule.so
-
Test the Command:
redis-cli 127.0.0.1:6379> mymodule.add 5 10 (integer) 15
Conclusion
In this section, you learned how to create custom Redis modules, including setting up the development environment, writing a basic module, and adding custom commands and data types. You also practiced creating a simple module that adds two integers. With this knowledge, you can extend Redis to meet your specific needs and integrate it more deeply into your applications.
Redis Course
Module 1: Introduction to Redis
Module 2: Redis Data Structures
Module 3: Redis Commands and Operations
Module 4: Redis Persistence
Module 5: Redis Security
Module 6: Redis Performance Optimization
Module 7: Redis Clustering and High Availability
Module 8: Redis Modules and Extensions
- Introduction to Redis Modules
- Popular Redis Modules
- Creating Custom Modules
- Using Redis with Other Technologies