En este tema, aprenderemos cómo crear módulos personalizados en Redis. Los módulos permiten extender la funcionalidad de Redis con comandos y tipos de datos personalizados, lo que puede ser muy útil para casos de uso específicos.

  1. Introducción a los Módulos Personalizados

¿Qué es un Módulo de Redis?

Un módulo de Redis es una extensión que permite agregar nuevas funcionalidades a Redis. Los módulos pueden incluir nuevos comandos, tipos de datos y otras características que no están disponibles en la versión estándar de Redis.

¿Por qué Crear un Módulo Personalizado?

  • Funcionalidad Extendida: Agregar comandos y tipos de datos específicos para tus necesidades.
  • Optimización: Mejorar el rendimiento para casos de uso específicos.
  • Integración: Facilitar la integración con otras tecnologías y sistemas.

  1. Configuración del Entorno

Requisitos Previos

  • Redis 4.0 o superior.
  • Conocimientos básicos de C (el lenguaje en el que se escriben los módulos de Redis).
  • Un entorno de desarrollo configurado con un compilador de C (como GCC).

Instalación de Redis

Si aún no tienes Redis instalado, puedes seguir estos pasos:

# Descargar Redis
wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable

# Compilar Redis
make

Configuración del Entorno de Desarrollo

Asegúrate de tener un compilador de C instalado. En sistemas basados en Debian, puedes instalar GCC con:

sudo apt-get update
sudo apt-get install build-essential

  1. Estructura Básica de un Módulo

Archivo de Cabecera

Cada módulo de Redis debe incluir el archivo de cabecera redismodule.h, que proporciona las funciones y macros necesarias para interactuar con Redis.

#include "redismodule.h"

Función de Inicialización

Cada módulo debe definir una función de inicialización que será llamada cuando el módulo se cargue en Redis.

int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (RedisModule_Init(ctx, "mymodule", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

Registro de Comandos

Para agregar un nuevo comando, debes registrarlo en la función de inicialización.

int MyCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    RedisModule_ReplyWithSimpleString(ctx, "Hello, Redis!");
    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.mycommand", MyCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

  1. Compilación y Carga del Módulo

Compilación

Guarda el código del módulo en un archivo llamado mymodule.c y compílalo con el siguiente comando:

gcc -o mymodule.so -shared -fPIC -I/path/to/redis/src mymodule.c

Carga del Módulo en Redis

Para cargar el módulo en Redis, agrega la siguiente línea a tu archivo de configuración de Redis (redis.conf):

loadmodule /path/to/mymodule.so

O carga el módulo en tiempo de ejecución con el comando MODULE LOAD:

redis-cli MODULE LOAD /path/to/mymodule.so

  1. Ejemplo Completo

Código del Módulo

#include "redismodule.h"

int MyCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (argc != 2) {
        return RedisModule_WrongArity(ctx);
    }
    const char *name = RedisModule_StringPtrLen(argv[1], NULL);
    RedisModule_ReplyWithFormat(ctx, "Hello, %s!", name);
    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.mycommand", MyCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

Compilación y Carga

gcc -o mymodule.so -shared -fPIC -I/path/to/redis/src mymodule.c
redis-cli MODULE LOAD /path/to/mymodule.so

Prueba del Módulo

redis-cli mymodule.mycommand "World"
# Output: "Hello, World!"

  1. Ejercicios Prácticos

Ejercicio 1: Crear un Comando de Suma

Crea un módulo que implemente un comando mymodule.sum que tome dos números como argumentos y devuelva su suma.

Solución

#include "redismodule.h"

int SumCommand(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_OK;
    }
    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.sum", SumCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

Ejercicio 2: Crear un Comando de Concatenación

Crea un módulo que implemente un comando mymodule.concat que tome dos cadenas como argumentos y devuelva su concatenación.

Solución

#include "redismodule.h"

int ConcatCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (argc != 3) {
        return RedisModule_WrongArity(ctx);
    }
    size_t len1, len2;
    const char *str1 = RedisModule_StringPtrLen(argv[1], &len1);
    const char *str2 = RedisModule_StringPtrLen(argv[2], &len2);

    RedisModuleString *result = RedisModule_CreateStringPrintf(ctx, "%s%s", str1, str2);
    RedisModule_ReplyWithString(ctx, result);
    RedisModule_FreeString(ctx, result);
    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.concat", ConcatCommand, "readonly", 0, 0, 0) == REDISMODULE_ERR) {
        return REDISMODULE_ERR;
    }
    return REDISMODULE_OK;
}

  1. Conclusión

En esta sección, hemos aprendido cómo crear módulos personalizados en Redis. Hemos cubierto la estructura básica de un módulo, cómo compilarlo y cargarlo en Redis, y hemos visto ejemplos prácticos de comandos personalizados. Con esta base, puedes empezar a crear tus propios módulos para extender la funcionalidad de Redis según tus necesidades específicas.

Resumen

  • Módulos de Redis: Extienden la funcionalidad de Redis con comandos y tipos de datos personalizados.
  • Configuración del Entorno: Necesitas Redis 4.0+, conocimientos de C y un compilador de C.
  • Estructura Básica: Incluye el archivo de cabecera redismodule.h, define una función de inicialización y registra comandos.
  • Compilación y Carga: Compila el módulo con GCC y cárgalo en Redis con MODULE LOAD.
  • Ejercicios Prácticos: Implementa comandos personalizados como mymodule.sum y mymodule.concat.

Con estos conocimientos, estás listo para explorar más a fondo las capacidades de los módulos de Redis y crear soluciones personalizadas para tus aplicaciones.

© Copyright 2024. Todos los derechos reservados