redis module模块简单使用
以往我們想給 Redis 加個功能或類似事務的東西只能用 Lua 腳本,這個東西沒有實現真正的原子性,另外也無法使用底層的 API ,實質上比單純的命令腳本提升有限。
Redis 4.0 終于加入了模塊,暴露了必要的 API,并且有自動內存管理(大大減輕編寫負擔),基于 C99(C++ 或者其它語言的 C 綁定接口當然也可以)。
這東西有多靈活呢?不知道作者是不是為了突出這一點,直接編寫了一個神經網絡模塊。
注意:
redis對布隆過濾器的支持就是通過第三方module來實現的,安裝,使用都很簡單
可以參考筆者的這篇博客:https://blog.csdn.net/yzf279533105/article/details/110873427
模塊 Module 可以動態的載入和卸載,可以實現底層的數據結構也可以調用高層的指令,這一切都只需要包含頭文件 redismodule.h ,和 Redis 本身一樣簡潔優雅。
基本入門
Hello World
// redis 4.0 以上源碼可以找到頭文件 #include "redismodule.h" #include <stdlib.h>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) {// 最先調用初始化if (RedisModule_Init(ctx,"helloworld",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR) return REDISMODULE_ERR;// 注冊命令if (RedisModule_CreateCommand(ctx,"helloworld.rand",HelloworldRand_RedisCommand) == REDISMODULE_ERR)return REDISMODULE_ERR;return REDISMODULE_OK; }編譯命令
g++ -fPIC -c mycal.cpp -o mycal.xo ld -o mycal.so mycal.xo -shared -lc一般我更喜歡用 cmake,管理起來更容易
cmake_minimum_required(VERSION 2.8.11) project(mycal)set(mycal mycal.so)add_library(${mycal} SHARED mycal.cpp) set_target_properties(${mycal} PROPERTIES PREFIX "" SUFFIX "")加載命令
MODULE LOAD /path/to/mymodule.so # 在 redis-cli 中執行,注意這里 mymodule.so 是文件名執行命令
helloworld.rand # 在 redis-cli 中執行基礎 API 一覽
#include "redismodule.h" // 這個頭文件在 > 4.0 的redis 源代碼可以找到 #include <stdlib.h>// redis API 和 argv 參數 都是 RedisModuleString 類型的 int HelloworldRand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {// 自動內存管理// 不需要 close keys/ free replies / free RedisModuleString// 注意為了及時處理內存,使用大內存應該手動 free (用redis對應函數)RedisModule_AutoMemory(ctx);// 錯誤調用可以使得 redis 直接崩潰,需要檢查參數if (argc != 3) return RedisModule_WrongArity(ctx);// 從 redis 字符串獲取數據const char *s = RedisModule_StringPtrLen(argv[0], NULL);// 字符串到數字long long myval;if (RedisModule_StringToLongLong(argv[1],&myval) == REDISMODULE_OK) {/* Do something with 'myval' */}// 數字到字符串RedisModuleString *mystr = RedisModule_CreateStringFromLongLong(ctx, 10);// 使用如下的函數而不是 malloc(對Redis透明,無法控制),保證和 redis 的內存分配器一致,默認是 jemalloc// void *RedisModule_Alloc(size_t bytes);// void* RedisModule_Realloc(void *ptr, size_t bytes);// void RedisModule_Free(void *ptr);// void RedisModule_Calloc(size_t nmemb, size_t size);// char *RedisModule_Strdup(const char *str);// 操作 Redis 原生類型底層API,通常是 RedisModule_TypeOperation 的格式命名函數RedisModuleKey *key;key = (RedisModuleKey*)RedisModule_OpenKey(ctx,argv[1],REDISMODULE_WRITE);if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {RedisModule_StringSet(key,argv[2]);}// 高層 API 用 RedisModule_CallRedisModuleCallReply *reply;// sc 是格式化標志位,表示命令的多個參數各是什么類型,s 代表 argv[1] 是一個 RedisModuleString// c 代表 “10” 是以 \0 結尾的 C 字符串reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {long long myval = RedisModule_CallReplyInteger(reply);/* Do something with myval. */}// 返回一個數值給調用者RedisModule_ReplyWithLongLong(ctx, rand());return REDISMODULE_OK; }// 必須的函數 extern "C" int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {// 模塊的名稱在這里注冊,可以跟編譯后 so 名字不一樣,推薦一樣// RedisModule_Init 必須在調用其它API前最先被調用if (RedisModule_Init(ctx, "mycal", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR)return REDISMODULE_ERR;// 與其它模塊命名沖突會導致命令注冊失敗,推薦采用 模塊名.命令名 方式if (RedisModule_CreateCommand(ctx, "mycal", HelloworldRand_RedisCommand, "write", 1,1,1) == REDISMODULE_ERR)return REDISMODULE_ERR; }模塊必須的函數只有 RedisModule_OnLoad,它是 redis 調用模塊的入口函數。
上面的語言是 C++ ,為了編譯成動態時函數的可見性加了 extern "C" 前綴。
用 C 語言開發是最簡單的,但事實上任何語言都可以開發 Redis 模塊。
?
在配置文件 redis.conf
增加: loadmoudule /path/module.so [argv0] [argv1] # 配置文件,后面可以加參數,這種方式需要重啟redis
客戶端工具 redis-cli
module load /path/module.so [argv0] [argv1] # 客戶端指令,加載模塊,不需要重啟redis,但是如果redis關閉后這個module需要重新加載
module list # 列出所有模塊
module unload module # 卸載模塊,模塊名是函數中注冊的名稱,不是文件名
API
大致可以分為三類:直接操作底層數據;redis 命令操作;內存分配、集群支持等
注意
模塊如果有沒有捕獲或內存泄露出錯等問題 Redis 本身是無法處理的,會導致程序整個掛掉,甚至很可能連日志都沒有需要非常小心。
參考文獻
總結
以上是生活随笔為你收集整理的redis module模块简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis之rehash原理
- 下一篇: 令牌桶限流之redis-cell的安装,