模块 API 参考
Redis 模块 API 参考
章节
- 堆分配原始函数
- 命令 API
- 模块信息和时间测量
- 模块的自动内存管理
- 字符串对象 API
- 回复 API
- 命令复制 API
- DB 和键 API - 通用 API
- 字符串类型的键 API
- 列表类型的键 API
- 排序集类型的键 API
- 排序集迭代器键 API
- 哈希类型的键 API
- 流类型的键 API
- 从模块调用 Redis 命令
- 模块数据类型
- RDB 加载和保存函数
- 键摘要 API(模块类型的 DEBUG DIGEST 接口)
- 模块数据类型的 AOF API
- IO 上下文处理
- 日志记录
- 从模块阻止客户端
- 线程安全上下文
- 模块键空间通知 API
- 模块集群 API
- 模块计时器 API
- 模块事件循环 API
- 模块 ACL API
- 模块字典 API
- 模块信息字段
- 模块实用程序 API
- 模块 API 导出/导入
- 模块命令过滤器 API
- 扫描键空间和哈希
- 模块 fork API
- 服务器钩子实现
- 模块配置 API
- RDB 加载/保存 API
- 键驱逐 API
- 其他 API
- 碎片整理 API
- 函数索引
堆分配原始函数
使用这些函数分配的内存将被 Redis 键驱逐算法考虑在内,并在 Redis 内存使用信息中报告。
RedisModule_Alloc
void *RedisModule_Alloc(size_t bytes);
自版本 4.0.0
像 malloc()
一样使用。使用此函数分配的内存将在 Redis INFO 内存中报告,用于根据 maxmemory 设置驱逐键,并且通常被视为 Redis 分配的内存。您应该避免使用 malloc()
。如果无法分配足够的内存,此函数将出现异常。
RedisModule_TryAlloc
void *RedisModule_TryAlloc(size_t bytes);
自版本 7.0.0
类似于 RedisModule_Alloc
,但在分配失败的情况下返回 NULL,而不是出现异常。
RedisModule_Calloc
void *RedisModule_Calloc(size_t nmemb, size_t size);
自版本 4.0.0
像 calloc()
一样使用。使用此函数分配的内存将在 Redis INFO 内存中报告,用于根据 maxmemory 设置驱逐键,并且通常被视为 Redis 分配的内存。您应该避免直接使用 calloc()
。
RedisModule_TryCalloc
void *RedisModule_TryCalloc(size_t nmemb, size_t size);
自版本 7.4.0
类似于 RedisModule_Calloc
,但在分配失败的情况下返回 NULL,而不是出现异常。
RedisModule_Realloc
void* RedisModule_Realloc(void *ptr, size_t bytes);
自版本 4.0.0
像 realloc()
一样使用,用于使用 RedisModule_Alloc()
获取的内存。
RedisModule_TryRealloc
void *RedisModule_TryRealloc(void *ptr, size_t bytes);
自版本 7.4.0
类似于 RedisModule_Realloc
,但在分配失败的情况下返回 NULL,而不是出现异常。
RedisModule_Free
void RedisModule_Free(void *ptr);
自版本 4.0.0
像 free()
一样使用,用于使用 RedisModule_Alloc()
和 RedisModule_Realloc()
获取的内存。但是,您绝不应尝试使用 RedisModule_Free()
释放模块内部使用 malloc()
分配的内存。
RedisModule_Strdup
char *RedisModule_Strdup(const char *str);
自版本 4.0.0
类似于 strdup()
,但返回使用 RedisModule_Alloc()
分配的内存。
RedisModule_PoolAlloc
void *RedisModule_PoolAlloc(RedisModuleCtx *ctx, size_t bytes);
自版本 4.0.0
返回堆分配的内存,该内存将在模块回调函数返回时自动释放。最适合短期存活的小型分配,并且必须在回调返回时释放。如果请求了至少一个字长字节,则返回的内存将对齐到架构字长,否则它只是对齐到下一个 2 的幂,因此例如 3 字节请求将对齐到 4 字节,而 2 字节请求将对齐到 2 字节。
没有 realloc 样式函数,因为当需要使用池分配器时,这不是一个好主意。
如果 bytes
为 0,则该函数返回 NULL。
命令 API
这些函数用于实现自定义 Redis 命令。
有关示例,请参阅 https://redis.ac.cn/topics/modules-intro。
RedisModule_IsKeysPositionRequest
int RedisModule_IsKeysPositionRequest(RedisModuleCtx *ctx);
自版本 4.0.0
如果使用“getkeys-api”标志声明的模块命令以特殊方式调用以获取键位置而不是执行,则返回非零值。否则返回零。
RedisModule_KeyAtPosWithFlags
void RedisModule_KeyAtPosWithFlags(RedisModuleCtx *ctx, int pos, int flags);
自版本 7.0.0
当以获取键位置的方式调用模块命令时,因为该命令在注册期间被标记为“getkeys-api”,命令实现使用 RedisModule_IsKeysPositionRequest()
API 检查此特殊调用并使用此函数来报告键。
支持的标志是 RedisModule_SetCommandInfo
使用的标志,请参阅 REDISMODULE_CMD_KEY_
*。
以下是如何使用它的示例
if (RedisModule_IsKeysPositionRequest(ctx)) {
RedisModule_KeyAtPosWithFlags(ctx, 2, REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_ACCESS);
RedisModule_KeyAtPosWithFlags(ctx, 1, REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE | REDISMODULE_CMD_KEY_ACCESS);
}
注意:在上面的示例中,获取键 API 可以通过键规范(首选)来处理。仅当无法声明涵盖所有键的键规范时,才需要实现 getkeys-api。
RedisModule_KeyAtPos
void RedisModule_KeyAtPos(RedisModuleCtx *ctx, int pos);
自版本 4.0.0
此 API 在添加 RedisModule_KeyAtPosWithFlags
之前就已经存在,现在已弃用,可以与旧版本(在引入键规范和标志之前)保持兼容。
RedisModule_IsChannelsPositionRequest
int RedisModule_IsChannelsPositionRequest(RedisModuleCtx *ctx);
自版本 7.0.0
如果使用“getchannels-api”标志声明的模块命令以特殊方式调用以获取通道位置而不是执行,则返回非零值。否则返回零。
RedisModule_ChannelAtPosWithFlags
void RedisModule_ChannelAtPosWithFlags(RedisModuleCtx *ctx,
int pos,
int flags);
自版本 7.0.0
当以获取通道位置的方式调用模块命令时,因为该命令在注册期间被标记为“getchannels-api”,命令实现使用 RedisModule_IsChannelsPositionRequest()
API 检查此特殊调用并使用此函数来报告通道。
支持的标志是
REDISMODULE_CMD_CHANNEL_SUBSCRIBE
:此命令将订阅该通道。REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE
:此命令将取消订阅该通道。REDISMODULE_CMD_CHANNEL_PUBLISH
:此命令将发布到该通道。REDISMODULE_CMD_CHANNEL_PATTERN
:而不是对特定通道执行操作,而是对由模式指定的任何通道执行操作。这与 Redis 中可用的 PSUBSCRIBE 和 PUNSUBSCRIBE 命令使用的访问权限相同。不适用于 PUBLISH 权限。
以下是如何使用它的示例
if (RedisModule_IsChannelsPositionRequest(ctx)) {
RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_SUBSCRIBE | REDISMODULE_CMD_CHANNEL_PATTERN);
RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_PUBLISH);
}
注意:声明通道的一种用途是评估 ACL 权限。在这种情况下,始终允许取消订阅,因此只会检查命令是否符合订阅和发布权限。这是使用 RedisModule_ACLCheckChannelPermissions
的首选方法,因为它允许在执行命令之前检查 ACL。
RedisModule_CreateCommand
int RedisModule_CreateCommand(RedisModuleCtx *ctx,
const char *name,
RedisModuleCmdFunc cmdfunc,
const char *strflags,
int firstkey,
int lastkey,
int keystep);
自版本 4.0.0
在 Redis 服务器中注册一个新命令,该命令将通过使用 RedisModule 调用约定调用函数指针“cmdfunc”来处理。
该函数在以下情况下返回 REDISMODULE_ERR
- 如果在
RedisModule_OnLoad
之外调用了模块命令的创建。 - 指定的命令已被占用。
- 命令名称包含一些不允许的字符。
- 传递了一组无效的标志。
否则返回 REDISMODULE_OK
并且注册了新命令。
此函数必须在模块的初始化期间在 RedisModule_OnLoad()
函数内部调用。在初始化函数之外调用此函数是未定义的。
命令函数类型如下
int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
并且应该始终返回 REDISMODULE_OK
。
标志集“strflags”指定了命令的行为,应该作为由空格分隔的单词组成的 C 字符串传递,例如“write deny-oom”。标志集如下
- “write”:命令可能会修改数据集(它也可能从它读取数据)。
- “readonly”:命令从键返回数据,但从不写入。
- “admin”:命令是管理命令(可能会更改复制或执行类似的任务)。
- “deny-oom”:命令可能会使用额外的内存,并且应该在内存不足的情况下拒绝。
- “deny-script”:不允许在 Lua 脚本中使用此命令。
- “allow-loading”:允许服务器加载数据时使用此命令。只有不与数据集交互的命令才应该被允许在此模式下运行。如果不确定,请勿使用此标志。
- “pubsub”:命令在发布/订阅频道上发布内容。
- “random”:即使从相同的输入参数和键值开始,命令也可能具有不同的输出。从 Redis 7.0 开始,此标志已弃用。使用命令提示可以将命令声明为“random”,请参阅 https://redis.ac.cn/topics/command-tips。
- “allow-stale”:允许命令在不提供陈旧数据的从属服务器上运行。如果您不知道这是什么意思,请勿使用它。
- “no-monitor”:不在监视器上传播命令。如果您要命令的论证中包含敏感数据,请使用它。
- “no-slowlog”:不要在慢日志中记录此命令。如果您要命令的论证中包含敏感数据,请使用它。
- “fast”:命令的时间复杂度不大于 O(log(N)),其中 N 是集合的大小或表示命令正常可扩展性问题的任何其他内容。
- “getkeys-api”:命令实现接口以返回作为键的论证。当 start/stop/step 不够用,因为命令语法的原因时使用。
- “no-cluster”:命令不应在 Redis 集群中注册,因为它不是为使用它而设计的,例如,无法报告键的位置,以编程方式创建键名称,或任何其他原因。
- “no-auth”:此命令可以由未经身份验证的客户端运行。通常,这用于用于对客户端进行身份验证的命令。
- “may-replicate”:此命令可能会生成复制流量,即使它不是写入命令。
- “no-mandatory-keys”:此命令可能接受的所有键都是可选的
- “blocking”:命令有可能阻塞客户端。
- “allow-busy”:允许命令在服务器被脚本或慢速模块命令阻塞时运行,请参阅 RedisModule_Yield。
- “getchannels-api”:命令实现接口以返回作为通道的论证。
最后三个参数指定新命令的哪些论证是 Redis 键。有关更多信息,请参阅 https://redis.ac.cn/commands/command。
firstkey
:第一个作为键的论证的基于一的索引。位置 0 始终是命令名称本身。对于没有键的命令,为 0。lastkey
:最后一个作为键的论证的基于一的索引。负数表示从最后一个论证倒数(-1 表示提供的最后一个论证)对于没有键的命令,为 0。keystep
:第一个和最后一个键索引之间的步长。对于没有键的命令,为 0。
此信息由 ACL、集群和 COMMAND
命令使用。
注意:上面描述的方案用途有限,只能用于查找位于固定索引处的键。对于非平凡的键论证,您可以传递 0,0,0 并使用 RedisModule_SetCommandInfo
使用更高级的方案设置键规范,并使用 RedisModule_SetCommandACLCategories
设置命令的 Redis ACL 类别。
RedisModule_GetCommand
RedisModuleCommand *RedisModule_GetCommand(RedisModuleCtx *ctx,
const char *name);
自版本 7.0.0
通过命令名称获取一个不透明的结构,表示模块命令。此结构用于一些与命令相关的 API 中。
在以下错误情况下返回 NULL
- 命令未找到
- 该命令不是模块命令
- 该命令不属于调用模块
RedisModule_CreateSubcommand
int RedisModule_CreateSubcommand(RedisModuleCommand *parent,
const char *name,
RedisModuleCmdFunc cmdfunc,
const char *strflags,
int firstkey,
int lastkey,
int keystep);
自版本 7.0.0
与 RedisModule_CreateCommand
非常相似,只是它用于创建与另一个容器命令关联的子命令。
示例:如果模块具有配置命令 MODULE.CONFIG,则 GET 和 SET 应该是单独的子命令,而 MODULE.CONFIG 是一个命令,但不能使用有效的 funcptr
注册
if (RedisModule_CreateCommand(ctx,"module.config",NULL,"",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
RedisModuleCommand *parent = RedisModule_GetCommand(ctx,,"module.config");
if (RedisModule_CreateSubcommand(parent,"set",cmd_config_set,"",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
if (RedisModule_CreateSubcommand(parent,"get",cmd_config_get,"",0,0,0) == REDISMODULE_ERR)
return REDISMODULE_ERR;
如果成功则返回 REDISMODULE_OK
,如果出现以下错误则返回 REDISMODULE_ERR
- 解析
strflags
时出错 - 命令标记为
no-cluster
,但启用了集群模式 parent
已经是子命令(我们不允许超过一个级别的命令嵌套)parent
是一个具有实现(RedisModuleCmdFunc
)的命令(父命令应该只是子命令的纯容器)parent
已经有一个名为name
的子命令- 创建子命令是在
RedisModule_OnLoad
之外调用的。
RedisModule_AddACLCategory
int RedisModule_AddACLCategory(RedisModuleCtx *ctx, const char *name);
自版本 7.4.0
RedisModule_AddACLCategory
可用于添加新的 ACL 命令类别。类别名称只能包含字母数字字符、下划线或连字符。类别只能在 RedisModule_OnLoad
函数中添加。添加类别后,不能删除。任何模块都可以使用 RedisModule_SetCommandACLCategories
将命令注册到任何添加的类别中。
返回值
- 成功添加新的 ACL 类别时返回
REDISMODULE_OK
。 - 失败时返回
REDISMODULE_ERR
。
发生错误时,errno 将设置为
- 如果名称包含无效字符,则为 EINVAL。
- 如果类别名称已存在,则为 EBUSY。
- 如果类别数量达到 64 个类别的最大限制,则为 ENOMEM。
RedisModule_SetCommandACLCategories
int RedisModule_SetCommandACLCategories(RedisModuleCommand *command,
const char *aclflags);
自版本 7.2.0
RedisModule_SetCommandACLCategories
可用于将 ACL 类别设置为模块命令和子命令。应将 ACL 类别的集合作为以空格分隔的 C 字符串 'aclflags' 传递。
例如,acl 标志 'write slow' 将命令标记为写入和慢速 ACL 类别的组成部分。
成功时返回 REDISMODULE_OK
。发生错误时返回 REDISMODULE_ERR
。
此函数只能在 RedisModule_OnLoad
函数中调用。如果在该函数之外调用,将返回错误。
RedisModule_SetCommandInfo
int RedisModule_SetCommandInfo(RedisModuleCommand *command,
const RedisModuleCommandInfo *info);
自版本 7.0.0
设置额外的命令信息。
影响 COMMAND
、COMMAND INFO
和 COMMAND DOCS
的输出,集群、ACL,并用于在调用到达模块代码之前过滤参数数量错误的命令。
此函数可以在使用 RedisModule_CreateCommand
创建命令并使用 RedisModule_GetCommand
获取命令指针后调用。每个命令的信息只能设置一次,并具有以下结构
typedef struct RedisModuleCommandInfo {
const RedisModuleCommandInfoVersion *version;
const char *summary;
const char *complexity;
const char *since;
RedisModuleCommandHistoryEntry *history;
const char *tips;
int arity;
RedisModuleCommandKeySpec *key_specs;
RedisModuleCommandArg *args;
} RedisModuleCommandInfo;
除了 version
之外的所有字段都是可选的。字段说明
-
version
:此字段允许与不同 Redis 版本兼容。始终将此字段设置为REDISMODULE_COMMAND_INFO_VERSION
。 -
summary
:命令的简短说明(可选)。 -
complexity
:复杂度说明(可选)。 -
since
:引入命令的版本(可选)。注意:指定的版本应该是模块的版本,而不是 Redis 版本。 -
history
:RedisModuleCommandHistoryEntry
数组(可选),它是一个具有以下字段的结构const char *since; const char *changes;
since
是一个版本字符串,changes
是一个描述更改的字符串。该数组以一个零值条目结束,即两个字符串都设置为 NULL 的条目。 -
tips
:关于此命令的空格分隔提示的字符串,供客户端和代理使用。请参阅 https://redis.ac.cn/topics/command-tips。 -
arity
:参数数量,包括命令名称本身。正数指定确切的参数数量,负数指定最小参数数量,因此使用 -N 表示 >= N。Redis 在将调用传递给模块之前会进行验证,因此这可以替换模块命令实现中的参数数量检查。如果命令有子命令,则值为 0(或省略的 arity 字段)等效于 -2,否则等效于 -1。 -
key_specs
:RedisModuleCommandKeySpec
数组,以一个 memset 为零的元素结束。这是一种方案,它试图比旧的RedisModule_CreateCommand
参数firstkey
、lastkey
、keystep
更好地描述键参数的位置,并且在上述三个参数不足以描述键位置时需要使用。获取键位置有两种步骤:开始搜索 (BS),其中索引应该找到第一个键,以及查找键 (FK),它相对于 BS 的输出,描述了如何找到哪些参数是键。此外,还有一些键特定的标志。键规范会导致在 RedisModule_CreateCommand 中给出的三元组 (firstkey, lastkey, keystep) 重新计算,但提供这三个参数在 RedisModule_CreateCommand 中仍然有用,以便更好地支持旧的 Redis 版本,其中 RedisModule_SetCommandInfo 不可用。
请注意,键规范并未完全取代“getkeys-api”(请参阅 RedisModule_CreateCommand、RedisModule_IsKeysPositionRequest 和 RedisModule_KeyAtPosWithFlags),因此最好同时提供键规范并实现 getkeys-api。
键规范具有以下结构
typedef struct RedisModuleCommandKeySpec { const char *notes; uint64_t flags; RedisModuleKeySpecBeginSearchType begin_search_type; union { struct { int pos; } index; struct { const char *keyword; int startfrom; } keyword; } bs; RedisModuleKeySpecFindKeysType find_keys_type; union { struct { int lastkey; int keystep; int limit; } range; struct { int keynumidx; int firstkey; int keystep; } keynum; } fk; } RedisModuleCommandKeySpec;
RedisModuleCommandKeySpec 字段说明
-
notes
:关于此键规范的可选说明或澄清。 -
flags
:下面描述的键规范标志的按位或运算。 -
begin_search_type
:这描述了如何发现第一个键。有两种方法可以确定第一个键REDISMODULE_KSPEC_BS_UNKNOWN
:无法确定键参数从何处开始。REDISMODULE_KSPEC_BS_INDEX
:键参数从一个恒定索引开始。REDISMODULE_KSPEC_BS_KEYWORD
:键参数从一个特定关键字之后开始。
-
bs
:这是一个联合体,根据begin_search_type
字段的值使用index
或keyword
分支。-
bs.index.pos
:从该索引开始搜索键。(仅限REDISMODULE_KSPEC_BS_INDEX
。) -
bs.keyword.keyword
:指示键参数开始的关键字(字符串)。(仅限REDISMODULE_KSPEC_BS_KEYWORD
。) -
bs.keyword.startfrom
:argv 中的索引,从该索引开始搜索。可以为负数,这意味着从末尾开始反向搜索。例如:-2 表示从倒数第二个参数开始反向搜索。(仅限REDISMODULE_KSPEC_BS_KEYWORD
。)
-
-
find_keys_type
:在“开始搜索”之后,这描述了哪些参数是键。策略是REDISMODULE_KSPEC_BS_UNKNOWN
:无法确定键参数的位置。REDISMODULE_KSPEC_FK_RANGE
:键在特定索引(或相对于最后一个参数)处结束。REDISMODULE_KSPEC_FK_KEYNUM
:有一个参数包含键参数的数量,该参数位于键本身之前。
如果此键规范准确描述了一个键,则可以省略
find_keys_type
和fk
。 -
fk
:这是一个联合体,根据find_keys_type
字段的值使用range
或keynum
分支。-
fk.range
(对于REDISMODULE_KSPEC_FK_RANGE
):一个具有以下字段的结构-
lastkey
:相对于开始搜索步骤结果的最后一个键的索引。可以为负数,在这种情况下,它不是相对的。-1 表示最后一个参数,-2 表示倒数第二个参数,依此类推。 -
keystep
:找到一个键后,应该跳过多少个参数才能找到下一个键? -
limit
:如果lastkey
为 -1,我们使用limit
来限制搜索的比例。0 和 1 表示没有限制。2 表示剩余参数的 1/2,3 表示 1/3,依此类推。
-
-
fk.keynum
(对于REDISMODULE_KSPEC_FK_KEYNUM
):一个具有以下字段的结构-
keynumidx
:包含即将到来的键数量的参数的索引,相对于开始搜索步骤结果。 -
firstkey
:相对于开始搜索步骤结果的第一个键的索引。(通常它正好位于keynumidx
之后,在这种情况下,应该将其设置为keynumidx + 1
。) -
keystep
:找到一个键后,应该跳过多少个参数才能找到下一个键?
-
-
键规范标志
前四个指的是命令对键的值或元数据实际执行的操作,而不是用户数据或它如何影响用户数据。每个键规范可能必须恰好有一个。任何不属于明确的删除、覆盖或只读操作的操作都将被标记为 RW。
-
REDISMODULE_CMD_KEY_RO
:只读。读取键的值,但不一定返回它。 -
REDISMODULE_CMD_KEY_RW
:读写。修改存储在键的值或其元数据中的数据。 -
REDISMODULE_CMD_KEY_OW
:覆盖。覆盖存储在键的值中的数据。 -
REDISMODULE_CMD_KEY_RM
:删除键。
接下来的四个指的是键值中的用户数据,而不是元数据,如 LRU、类型、基数。它指的是对用户数据(实际输入字符串或 TTL)的逻辑操作,被使用/返回/复制/更改。它不涉及元数据(如类型、计数、数据是否存在)的修改或返回。
-
REDISMODULE_CMD_KEY_ACCESS
:返回、复制或使用来自键的值的用户数据。 -
REDISMODULE_CMD_KEY_UPDATE
:更新数据到值,新值可能取决于旧值。 -
REDISMODULE_CMD_KEY_INSERT
:将数据添加到值中,而不会修改或删除现有数据。 -
REDISMODULE_CMD_KEY_DELETE
:显式地从键的值中删除一些内容。
其他标志
-
REDISMODULE_CMD_KEY_NOT_KEY
:键实际上不是一个键,但在集群模式下应该像键一样路由。 -
REDISMODULE_CMD_KEY_INCOMPLETE
:键规范可能没有指明它应该覆盖的所有键。 -
REDISMODULE_CMD_KEY_VARIABLE_FLAGS
:某些键可能具有不同的标志,具体取决于参数。
-
-
args
:RedisModuleCommandArg
数组,以一个 memset 为零的元素结束。RedisModuleCommandArg
是一个结构,具有以下描述的字段。typedef struct RedisModuleCommandArg { const char *name; RedisModuleCommandArgType type; int key_spec_index; const char *token; const char *summary; const char *since; int flags; struct RedisModuleCommandArg *subargs; } RedisModuleCommandArg;
字段说明
-
name
:参数的名称。 -
type
:参数的类型。有关详细信息,请参见下文。REDISMODULE_ARG_TYPE_ONEOF
和REDISMODULE_ARG_TYPE_BLOCK
类型要求参数具有子参数,即subargs
。 -
key_spec_index
:如果type
为REDISMODULE_ARG_TYPE_KEY
,则必须提供与该参数关联的键规范的索引。请参见上面的key_specs
。如果参数不是键,则可以指定 -1。 -
token
:参数前面的标记(可选)。例如:SET
中的参数seconds
具有标记EX
。如果参数仅由一个标记组成(例如SET
中的NX
),则类型应为REDISMODULE_ARG_TYPE_PURE_TOKEN
,value
应为 NULL。 -
summary
:参数的简短说明(可选)。 -
since
:包含此参数的第一个版本(可选)。 -
flags
:REDISMODULE_CMD_ARG_*
宏的按位或运算。请参见下文。 -
value
:参数的显示值。此字符串是在从COMMAND
的输出创建命令语法时应该显示的内容。如果token
不为 NULL,也应该显示它。
RedisModuleCommandArgType
说明REDISMODULE_ARG_TYPE_STRING
:字符串参数。REDISMODULE_ARG_TYPE_INTEGER
:整数参数。REDISMODULE_ARG_TYPE_DOUBLE
:双精度浮点参数。REDISMODULE_ARG_TYPE_KEY
:表示键名的字符串参数。REDISMODULE_ARG_TYPE_PATTERN
:字符串,但为正则表达式模式。REDISMODULE_ARG_TYPE_UNIX_TIME
:整数,但为 Unix 时间戳。REDISMODULE_ARG_TYPE_PURE_TOKEN
:参数没有占位符。它只是一个没有值的标记。例如:SET
命令的KEEPTTL
选项。REDISMODULE_ARG_TYPE_ONEOF
:当用户只能选择几个子参数中的一个时使用。需要subargs
。例如:SET
命令的NX
和XX
选项。REDISMODULE_ARG_TYPE_BLOCK
:当想要将多个子参数分组在一起时使用,通常是将它们全部应用于某些内容,例如使整个组“可选”。需要subargs
。例如:ZRANGE
中的LIMIT offset count
参数。
命令参数标志说明
REDISMODULE_CMD_ARG_OPTIONAL
:参数是可选的(例如SET
命令中的GET
)。REDISMODULE_CMD_ARG_MULTIPLE
:参数可以重复出现(例如DEL
中的 key)。REDISMODULE_CMD_ARG_MULTIPLE_TOKEN
:参数可以重复出现,其标记也可以重复出现(例如SORT
中的GET pattern
)。
-
成功时返回 REDISMODULE_OK
。错误时返回 REDISMODULE_ERR
,如果提供的信息无效则将 errno
设置为 EINVAL,如果信息已设置则设置为 EEXIST。如果信息无效,将记录一条警告,解释信息中的哪个部分无效以及原因。
模块信息和时间测量
RedisModule_IsModuleNameBusy
int RedisModule_IsModuleNameBusy(const char *name);
自版本 4.0.3
如果模块名称被占用,则返回非零值。否则返回零。
RedisModule_Milliseconds
mstime_t RedisModule_Milliseconds(void);
自版本 4.0.0
返回当前以毫秒为单位的 UNIX 时间。
RedisModule_MonotonicMicroseconds
uint64_t RedisModule_MonotonicMicroseconds(void);
自版本 7.0.0
返回相对于任意时间点的微秒计数器。
RedisModule_Microseconds
ustime_t RedisModule_Microseconds(void);
自版本 7.2.0
返回当前以微秒为单位的 UNIX 时间
RedisModule_CachedMicroseconds
ustime_t RedisModule_CachedMicroseconds(void);
自版本 7.2.0
返回以微秒为单位的缓存 UNIX 时间。它在服务器 cron 作业中更新,并在执行命令之前更新。它对复杂的调用栈很有用,例如一个命令导致一个键空间通知,导致一个模块执行一个 RedisModule_Call
,导致另一个通知,等等。所有这些回调使用相同的时钟是有意义的。
RedisModule_BlockedClientMeasureTimeStart
int RedisModule_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc);
自版本 6.2.0
标记一个时间点,该时间点将用作计算经过执行时间时的开始时间,当调用 RedisModule_BlockedClientMeasureTimeEnd()
时。在同一个命令中,您可以多次调用 RedisModule_BlockedClientMeasureTimeStart()
和 RedisModule_BlockedClientMeasureTimeEnd()
以将独立的时间间隔累积到后台持续时间。此方法始终返回 REDISMODULE_OK
。
此函数不是线程安全的,如果在模块线程和阻塞回调(可能为主线程)中同时使用,建议使用调用者拥有的锁来保护它们,而不是 GIL。
RedisModule_BlockedClientMeasureTimeEnd
int RedisModule_BlockedClientMeasureTimeEnd(RedisModuleBlockedClient *bc);
自版本 6.2.0
标记一个时间点,该时间点将用作计算经过执行时间时的结束时间。成功时返回 REDISMODULE_OK
。此方法仅在以前未定义开始时间(意味着未调用 RedisModule_BlockedClientMeasureTimeStart
)时返回 REDISMODULE_ERR
。
此函数不是线程安全的,如果在模块线程和阻塞回调(可能为主线程)中同时使用,建议使用调用者拥有的锁来保护它们,而不是 GIL。
RedisModule_Yield
void RedisModule_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply);
自版本 7.0.0
此 API 允许模块让 Redis 处理后台任务,以及模块命令的长时间阻塞执行期间的一些命令。模块可以定期调用此 API。flags 是以下这些位的掩码
REDISMODULE_YIELD_FLAG_NONE
:无特殊标志,可以执行一些后台操作,但不能处理客户端命令。REDISMODULE_YIELD_FLAG_CLIENTS
:Redis 也可以处理客户端命令。
busy_reply
参数是可选的,可用于控制 -BUSY
错误代码后的详细错误字符串。
当使用 REDISMODULE_YIELD_FLAG_CLIENTS
时,Redis 只有在 busy-reply-threshold
配置定义的时间之后才会开始处理客户端命令,在这种情况下,Redis 将开始用 -BUSY
错误拒绝大多数命令,但允许标记有 allow-busy
标志的命令执行。此 API 也可以在线程安全上下文中(在锁定状态下)使用,以及在加载期间(在 rdb_load
回调中,在这种情况下,它将用 -LOADING 错误拒绝命令)。
RedisModule_SetModuleOptions
void RedisModule_SetModuleOptions(RedisModuleCtx *ctx, int options);
自版本 6.0.0
设置定义功能或行为位标志的标志。
REDISMODULE_OPTIONS_HANDLE_IO_ERRORS
:通常,模块不需要为此费心,因为如果发生读取错误,进程只会终止,但是,设置此标志将允许 repl-diskless-load 在启用时工作。模块应该在读取之后使用 RedisModule_IsIOError
,然后使用已读取的数据,如果发生错误,则将其向上传播,并能够释放部分填充的值及其所有分配。
REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED
:请参阅 RedisModule_SignalModifiedKey()
。
REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD
:设置此标志表示模块知道无磁盘异步复制 (repl-diskless-load=swapdb),并且 Redis 可以在复制期间为读取提供服务,而不是用 LOADING 状态阻塞。
REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS
:声明模块希望获得嵌套的键空间通知。默认情况下,Redis 不会触发在键空间通知回调内部发生的键空间通知。此标志允许更改此行为并触发嵌套的键空间通知。注意:如果启用,模块应该保护自己免受无限递归。
RedisModule_SignalModifiedKey
int RedisModule_SignalModifiedKey(RedisModuleCtx *ctx,
RedisModuleString *keyname);
自版本 6.0.0
信号表明键已从用户的角度进行了修改(即使 WATCH 和客户端端缓存失效)。
当打开以供写入的键关闭时,会自动执行此操作,除非使用 RedisModule_SetModuleOptions()
设置了选项 REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED
。
模块的自动内存管理
RedisModule_AutoMemory
void RedisModule_AutoMemory(RedisModuleCtx *ctx);
自版本 4.0.0
启用自动内存管理。
该函数必须作为想要使用自动内存的命令实现的第一个函数调用。
启用后,自动内存管理会跟踪并在命令返回后自动释放键、调用回复和 Redis 字符串对象。在大多数情况下,这消除了调用以下函数的必要性
即使启用了自动内存管理,这些函数仍然可以使用,例如,为了优化执行大量分配的循环。
字符串对象 API
RedisModule_CreateString
RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx,
const char *ptr,
size_t len);
自版本 4.0.0
创建一个新的模块字符串对象。返回的字符串必须使用 RedisModule_FreeString()
释放,除非启用了自动内存。
字符串是通过复制从 ptr
开始的 len
字节创建的。不会保留对传递的缓冲区的引用。
模块上下文 'ctx' 是可选的,如果要从上下文范围之外创建字符串,则可以为 NULL。但是,在这种情况下,自动内存管理将不可用,并且必须手动管理字符串内存。
RedisModule_CreateStringPrintf
RedisModuleString *RedisModule_CreateStringPrintf(RedisModuleCtx *ctx,
const char *fmt,
...);
自版本 4.0.0
从 printf 格式和参数创建一个新的模块字符串对象。返回的字符串必须使用 RedisModule_FreeString()
释放,除非启用了自动内存。
字符串是使用 sds 格式化函数 sdscatvprintf()
创建的。
传递的上下文 'ctx' 可以为 NULL(如果需要),有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_CreateStringFromLongLong
RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx,
long long ll);
自版本 4.0.0
与 RedisModule_CreateString()
相似,但创建的字符串从 long long
整数开始,而不是获取缓冲区及其长度。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
传递的上下文 'ctx' 可以为 NULL(如果需要),有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_CreateStringFromULongLong
RedisModuleString *RedisModule_CreateStringFromULongLong(RedisModuleCtx *ctx,
unsigned long long ull);
自版本 7.0.3
与 RedisModule_CreateString()
相似,但创建的字符串从 unsigned long long
整数开始,而不是获取缓冲区及其长度。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
传递的上下文 'ctx' 可以为 NULL(如果需要),有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_CreateStringFromDouble
RedisModuleString *RedisModule_CreateStringFromDouble(RedisModuleCtx *ctx,
double d);
自版本 6.0.0
与 RedisModule_CreateString()
相似,但创建的字符串从 double 开始,而不是获取缓冲区及其长度。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
RedisModule_CreateStringFromLongDouble
RedisModuleString *RedisModule_CreateStringFromLongDouble(RedisModuleCtx *ctx,
long double ld,
int humanfriendly);
自版本 6.0.0
与 RedisModule_CreateString()
相似,但创建的字符串从 long double 开始。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
传递的上下文 'ctx' 可以为 NULL(如果需要),有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_CreateStringFromString
RedisModuleString *RedisModule_CreateStringFromString(RedisModuleCtx *ctx,
const RedisModuleString *str);
自版本 4.0.0
与 RedisModule_CreateString()
相似,但创建的字符串从另一个 RedisModuleString
开始。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
传递的上下文 'ctx' 可以为 NULL(如果需要),有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_CreateStringFromStreamID
RedisModuleString *RedisModule_CreateStringFromStreamID(RedisModuleCtx *ctx,
const RedisModuleStreamID *id);
自版本 6.2.0
从流 ID 创建一个字符串。返回的字符串必须使用 RedisModule_FreeString()
释放,除非启用了自动内存。
传递的上下文 ctx
可以为 NULL(如果需要)。有关更多信息,请参阅 RedisModule_CreateString()
文档。
RedisModule_FreeString
void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str);
自版本 4.0.0
释放使用返回新字符串对象的某个 Redis 模块 API 调用获得的模块字符串对象。
即使启用了自动内存管理,也可以调用此函数。在这种情况下,字符串将尽快释放并从要释放的字符串池中删除。
如果字符串是使用 NULL 上下文 'ctx' 创建的,也可以在释放字符串时将 ctx 作为 NULL 传递(但传递上下文不会造成任何问题)。使用上下文创建的字符串也应该在传递上下文时释放,因此,如果要稍后释放上下文之外的字符串,请确保使用 NULL 上下文创建它。
此 API 不是线程安全的,必须在锁定 GIL 的情况下访问这些保留的字符串(如果它们来自客户端命令参数)。
RedisModule_RetainString
void RedisModule_RetainString(RedisModuleCtx *ctx, RedisModuleString *str);
自版本 4.0.0
对该函数的每次调用都会使字符串 'str' 需要额外调用 RedisModule_FreeString()
才能真正释放字符串。请注意,启用模块自动内存管理获得的字符串的自动释放计数为一次 RedisModule_FreeString()
调用(它只是自动执行)。
通常,当以下条件同时满足时,您希望调用此函数
- 您启用了自动内存管理。
- 您要创建字符串对象。
- 您创建的这些字符串对象需要在创建它们的回调函数(例如命令实现)返回后仍然存在。
通常,您需要这样做是为了将创建的字符串对象存储到您自己的数据结构中,例如,在实现新的数据类型时。
请注意,当关闭内存管理时,您不需要调用 RetainString(),因为创建字符串将始终导致在回调函数返回后仍然存在的字符串,如果未执行 FreeString() 调用。
可以将 NULL 上下文传递给此函数。
当字符串要保留较长时间时,最好也调用 RedisModule_TrimStringAllocation()
以优化内存使用率。
从其他线程引用保留字符串的线程化模块必须在保留字符串后立即显式地修剪分配。不这样做可能会导致自动修剪,而自动修剪不是线程安全的。
此 API 不是线程安全的,必须在锁定 GIL 的情况下访问这些保留的字符串(如果它们来自客户端命令参数)。
RedisModule_HoldString
RedisModuleString* RedisModule_HoldString(RedisModuleCtx *ctx,
RedisModuleString *str);
自版本 6.0.7
此函数可以代替 RedisModule_RetainString()
使用。两者之间的主要区别在于,此函数将始终成功,而 RedisModule_RetainString()
可能由于断言而失败。
该函数返回指向 RedisModuleString
的指针,该指针由调用者拥有。当上下文的自动内存管理被禁用时,它需要调用 RedisModule_FreeString()
来释放字符串。当自动内存管理启用时,您可以选择调用 RedisModule_FreeString()
或让自动释放它。
此函数比 RedisModule_CreateStringFromString()
更有效率,因为它只要可能,就会避免复制底层的 RedisModuleString
。使用此函数的缺点是,可能无法对返回的 RedisModuleString
使用 RedisModule_StringAppendBuffer()
。
可以将 NULL 上下文传递给此函数。
当字符串要保留较长时间时,最好也调用 RedisModule_TrimStringAllocation()
以优化内存使用率。
从其他线程引用保留字符串的线程化模块必须在保留字符串后立即显式地修剪分配。不这样做可能会导致自动修剪,而自动修剪不是线程安全的。
此 API 不是线程安全的,必须在锁定 GIL 的情况下访问这些保留的字符串(如果它们来自客户端命令参数)。
RedisModule_StringPtrLen
const char *RedisModule_StringPtrLen(const RedisModuleString *str,
size_t *len);
自版本 4.0.0
给定一个字符串模块对象,此函数返回字符串的指针和长度。返回的指针和长度应仅用于只读访问,切勿修改。
RedisModule_StringToLongLong
int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll);
自版本 4.0.0
将字符串转换为 long long
整数,将其存储在 *ll
中。成功时返回 REDISMODULE_OK
。如果字符串无法解析为有效的、严格的 long long
(在前后没有空格),则返回 REDISMODULE_ERR
。
RedisModule_StringToULongLong
int RedisModule_StringToULongLong(const RedisModuleString *str,
unsigned long long *ull);
自版本 7.0.3
将字符串转换为 unsigned long long
整数,将其存储在 *ull
中。成功时返回 REDISMODULE_OK
。如果字符串无法解析为有效的、严格的 unsigned long long
(在前后没有空格),则返回 REDISMODULE_ERR
。
RedisModule_StringToDouble
int RedisModule_StringToDouble(const RedisModuleString *str, double *d);
自版本 4.0.0
将字符串转换为双精度浮点数,并将其存储在*d
中。如果字符串不是双精度浮点数的有效字符串表示,则返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
。
RedisModule_StringToLongDouble
int RedisModule_StringToLongDouble(const RedisModuleString *str,
long double *ld);
自版本 6.0.0
将字符串转换为长双精度浮点数,并将其存储在*ld
中。如果字符串不是双精度浮点数的有效字符串表示,则返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
。
RedisModule_StringToStreamID
int RedisModule_StringToStreamID(const RedisModuleString *str,
RedisModuleStreamID *id);
自版本 6.2.0
将字符串转换为流 ID,并将其存储在*id
中。如果字符串不是流 ID 的有效字符串表示,则返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
。特殊 ID “+” 和 “-” 是允许的。
RedisModule_StringCompare
int RedisModule_StringCompare(const RedisModuleString *a,
const RedisModuleString *b);
自版本 4.0.0
比较两个字符串对象,如果 a < b、a == b、a > b,则分别返回 -1、0 或 1。字符串以字节为单位进行比较,如同两个二进制块,不进行任何编码处理或整理尝试。
RedisModule_StringAppendBuffer
int RedisModule_StringAppendBuffer(RedisModuleCtx *ctx,
RedisModuleString *str,
const char *buf,
size_t len);
自版本 4.0.0
将指定的缓冲区追加到字符串 'str' 中。字符串必须是用户创建的,并且仅被引用一次,否则将返回REDISMODULE_ERR
,并且不会执行操作。
RedisModule_TrimStringAllocation
void RedisModule_TrimStringAllocation(RedisModuleString *str);
自版本 7.0.0
修剪为RedisModuleString
分配的可能过多的内存。
有时,RedisModuleString
可能为其分配了比实际需要的更多的内存,通常是为了从网络缓冲区构造的 argv 参数。此函数通过重新分配其内存来优化这些字符串,这对于那些不是短命字符串而是长时间保留的字符串很有用。
此操作**不是线程安全的**,应仅在保证没有对字符串的并发访问时调用。在字符串可能对其他线程可用之前,在模块命令中将其用于 argv 字符串通常是安全的。
目前,Redis 也可以在模块命令返回时自动修剪保留的字符串。但是,显式执行此操作仍然是首选选项。
- 将来版本的 Redis 可能会放弃自动修剪。
- 当前实现的自动修剪**不是线程安全的**。一个操作最近保留字符串的后台线程可能会与自动修剪发生竞争条件,从而导致数据损坏。
回复 API
这些函数用于向客户端发送回复。
大多数函数始终返回REDISMODULE_OK
,因此您可以将其与 'return' 一起使用,以使用以下方法从命令实现中返回
if (... some condition ...)
return RedisModule_ReplyWithLongLong(ctx,mycount);
带有集合函数的回复
在开始集合回复后,模块必须调用其他ReplyWith*
样式函数才能发出集合的元素。集合类型包括:数组、映射、集合和属性。
在生成元素数量未知的集合时,可以使用特殊标志REDISMODULE_POSTPONED_LEN
(以前称为REDISMODULE_POSTPONED_ARRAY_LEN
)调用该函数,并且可以使用RedisModule_ReplySet
*Length() 调用(如果有多个,则将设置最新的“打开”计数)来设置实际元素数量。
RedisModule_WrongArity
int RedisModule_WrongArity(RedisModuleCtx *ctx);
自版本 4.0.0
发送有关提供给命令的参数数量的错误,并在错误消息中引用命令名称。返回REDISMODULE_OK
。
示例
if (argc != 3) return RedisModule_WrongArity(ctx);
RedisModule_ReplyWithLongLong
int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll);
自版本 4.0.0
向客户端发送一个整数回复,其中包含指定的long long
值。该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithError
int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err);
自版本 4.0.0
回复错误 'err'。
注意,'err' 必须包含所有错误,包括初始错误代码。该函数仅提供初始“-”,因此用法如下:
RedisModule_ReplyWithError(ctx,"ERR Wrong Type");
而不是仅仅
RedisModule_ReplyWithError(ctx,"Wrong Type");
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithErrorFormat
int RedisModule_ReplyWithErrorFormat(RedisModuleCtx *ctx,
const char *fmt,
...);
自版本 7.2.0
回复从 printf 格式和参数创建的错误。
注意,'fmt' 必须包含所有错误,包括初始错误代码。该函数仅提供初始“-”,因此用法如下:
RedisModule_ReplyWithErrorFormat(ctx,"ERR Wrong Type: %s",type);
而不是仅仅
RedisModule_ReplyWithErrorFormat(ctx,"Wrong Type: %s",type);
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithSimpleString
int RedisModule_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg);
自版本 4.0.0
回复一个简单字符串(在 RESP 协议中为+... \r\n
)。这些回复仅适用于发送小型非二进制字符串,其开销很小,例如“OK”或类似的回复。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithArray
int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len);
自版本 4.0.0
回复一个包含 'len' 个元素的数组类型。
在开始数组回复后,模块必须调用其他ReplyWith*
样式函数,才能发出数组的元素。有关更多详细信息,请参见回复 API 部分。
使用RedisModule_ReplySetArrayLength()
来设置延迟长度。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithMap
int RedisModule_ReplyWithMap(RedisModuleCtx *ctx, long len);
自版本 7.0.0
回复一个包含 'len' 个对的 RESP3 映射类型。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
在开始映射回复后,模块必须调用其他ReplyWith*
样式函数,才能发出映射的元素。有关更多详细信息,请参见回复 API 部分。
如果连接的客户端使用的是 RESP2,则回复将转换为平面数组。
使用RedisModule_ReplySetMapLength()
来设置延迟长度。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithSet
int RedisModule_ReplyWithSet(RedisModuleCtx *ctx, long len);
自版本 7.0.0
回复一个包含 'len' 个元素的 RESP3 集合类型。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
在开始集合回复后,模块必须调用其他ReplyWith*
样式函数才能发出集合的元素。有关更多详细信息,请参见回复 API 部分。
如果连接的客户端使用的是 RESP2,则回复将转换为数组类型。
使用RedisModule_ReplySetSetLength()
来设置延迟长度。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithAttribute
int RedisModule_ReplyWithAttribute(RedisModuleCtx *ctx, long len);
自版本 7.0.0
向回复添加属性(元数据)。应在添加实际回复之前完成。请参阅https://github.com/antirez/RESP3/blob/master/spec.md#attribute-type
在开始属性回复后,模块必须调用其他ReplyWith*
样式函数才能发出属性映射的元素。有关更多详细信息,请参见回复 API 部分。
使用RedisModule_ReplySetAttributeLength()
来设置延迟长度。
RESP2 不支持,并将返回REDISMODULE_ERR
,否则该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithNullArray
int RedisModule_ReplyWithNullArray(RedisModuleCtx *ctx);
自版本 6.0.0
使用空数组回复客户端,在 RESP3 中为 null,在 RESP2 中为 null 数组。
注意:在 RESP3 中,空回复和空数组回复之间没有区别,因此为了避免歧义,最好避免使用此 API,而应使用RedisModule_ReplyWithNull
。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithEmptyArray
int RedisModule_ReplyWithEmptyArray(RedisModuleCtx *ctx);
自版本 6.0.0
使用空数组回复客户端。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplySetArrayLength
void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len);
自版本 4.0.0
当使用参数REDISMODULE_POSTPONED_LEN
调用RedisModule_ReplyWithArray()
时,因为我们事先不知道要作为数组元素输出的项目数量,所以此函数将负责设置数组长度。
由于可以有多个长度未知的待定数组回复,因此此函数保证始终设置以延迟方式创建的最新数组长度。
例如,为了输出一个类似于 [1,[10,20,30]] 的数组,我们可以编写
RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
RedisModule_ReplyWithLongLong(ctx,1);
RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
RedisModule_ReplyWithLongLong(ctx,10);
RedisModule_ReplyWithLongLong(ctx,20);
RedisModule_ReplyWithLongLong(ctx,30);
RedisModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.
RedisModule_ReplySetArrayLength(ctx,2); // Set len of top array
注意,在上面的示例中,没有理由推迟数组长度,因为我们生成了固定数量的元素,但在实践中,代码可能会使用迭代器或其他方法来创建输出,因此难以预先计算元素数量。
RedisModule_ReplySetMapLength
void RedisModule_ReplySetMapLength(RedisModuleCtx *ctx, long len);
自版本 7.0.0
与RedisModule_ReplySetArrayLength
非常相似,除了len
应该是映射上下文中调用的ReplyWith*
函数数量的一半。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
RedisModule_ReplySetSetLength
void RedisModule_ReplySetSetLength(RedisModuleCtx *ctx, long len);
自版本 7.0.0
与RedisModule_ReplySetArrayLength
非常相似。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
RedisModule_ReplySetAttributeLength
void RedisModule_ReplySetAttributeLength(RedisModuleCtx *ctx, long len);
自版本 7.0.0
与RedisModule_ReplySetMapLength
非常相似。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
如果RedisModule_ReplyWithAttribute
返回了错误,则不得调用此函数。
RedisModule_ReplyWithStringBuffer
int RedisModule_ReplyWithStringBuffer(RedisModuleCtx *ctx,
const char *buf,
size_t len);
自版本 4.0.0
回复一个块字符串,输入一个 C 缓冲区指针和长度。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithCString
int RedisModule_ReplyWithCString(RedisModuleCtx *ctx, const char *buf);
自版本 5.0.6
回复一个块字符串,输入一个 C 缓冲区指针,该指针被假定为以空字符结尾。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithString
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);
自版本 4.0.0
回复一个块字符串,输入一个RedisModuleString
对象。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithEmptyString
int RedisModule_ReplyWithEmptyString(RedisModuleCtx *ctx);
自版本 6.0.0
回复一个空字符串。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithVerbatimStringType
int RedisModule_ReplyWithVerbatimStringType(RedisModuleCtx *ctx,
const char *buf,
size_t len,
const char *ext);
自版本 7.0.0
回复一个二进制安全字符串,该字符串不应转义或过滤,输入一个 C 缓冲区指针、长度和一个 3 个字符的类型/扩展。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithVerbatimString
int RedisModule_ReplyWithVerbatimString(RedisModuleCtx *ctx,
const char *buf,
size_t len);
自版本 6.0.0
回复一个二进制安全字符串,该字符串不应转义或过滤,输入一个 C 缓冲区指针和长度。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithNull
int RedisModule_ReplyWithNull(RedisModuleCtx *ctx);
自版本 4.0.0
使用 NULL 回复客户端。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithBool
int RedisModule_ReplyWithBool(RedisModuleCtx *ctx, int b);
自版本 7.0.0
回复一个 RESP3 布尔类型。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
在 RESP3 中,这是布尔类型,在 RESP2 中,它是分别对应于 true 和 false 的 “1” 和 “0” 字符串响应。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithCallReply
int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx,
RedisModuleCallReply *reply);
自版本 4.0.0
回复 Redis 命令使用RedisModule_Call()
返回给我们内容的精确副本。当我们使用RedisModule_Call()
执行某些命令时,此函数很有用,因为我们希望向客户端回复与命令获得的相同回复。
返回值
- 成功时返回
REDISMODULE_OK
。 - 如果给定的回复是 RESP3 格式,但客户端期望的是 RESP2,则返回
REDISMODULE_ERR
。如果发生错误,则由模块编写者负责将回复转换为 RESP2(或通过返回错误来以其他方式处理它)。请注意,为了方便模块编写者,可以将0
作为RedisModule_Call
的 fmt 参数传递,以便RedisModuleCallReply
将以与当前客户端上下文相同的协议(RESP2 或 RESP3)返回。
RedisModule_ReplyWithDouble
int RedisModule_ReplyWithDouble(RedisModuleCtx *ctx, double d);
自版本 4.0.0
回复一个 RESP3 双精度类型。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
发送通过将双精度 'd' 转换为块字符串而获得的字符串回复。此函数基本上等同于将双精度转换为 C 缓冲区中的字符串,然后使用该缓冲区和长度调用函数RedisModule_ReplyWithStringBuffer()
。
在 RESP3 中,字符串被标记为双精度,而在 RESP2 中,它只是一个普通的字符串,用户必须对其进行解析。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithBigNumber
int RedisModule_ReplyWithBigNumber(RedisModuleCtx *ctx,
const char *bignum,
size_t len);
自版本 7.0.0
回复一个 RESP3 大数类型。访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关 RESP3 的更多信息。
在 RESP3 中,这是一个长度为len
的字符串,它被标记为大数,但是,确保它是有效的大数是调用者的责任。在 RESP2 中,这只是一个普通的块字符串响应。
该函数始终返回REDISMODULE_OK
。
RedisModule_ReplyWithLongDouble
int RedisModule_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld);
自版本 6.0.0
将长双精度浮点数 'ld' 转换为一个块字符串后,发送一个字符串回复。此函数基本上等同于将长双精度浮点数转换为字符串并放入 C 缓冲区,然后使用该缓冲区和长度调用函数 RedisModule_ReplyWithStringBuffer()
。双精度字符串使用人类可读的格式(参见 networking.c 中的 addReplyHumanLongDouble
)。
该函数始终返回REDISMODULE_OK
。
命令复制 API
RedisModule_Replicate
int RedisModule_Replicate(RedisModuleCtx *ctx,
const char *cmdname,
const char *fmt,
...);
自版本 4.0.0
将指定的命令和参数复制到从服务器和 AOF,作为调用命令实现执行的结果。
复制的命令始终被包装在一个 MULTI/EXEC 中,该 MULTI/EXEC 包含在给定的模块命令执行中复制的所有命令,按执行顺序排列。
模块应该尽量使用其中一个接口。
此命令完全遵循 RedisModule_Call()
的相同接口,因此必须传递一组格式说明符,然后传递与提供的格式说明符匹配的参数。
有关详细信息,请参阅 RedisModule_Call()
。
使用特殊的 "A" 和 "R" 修饰符,调用者可以从指定命令的传播中排除 AOF 或复制。否则,默认情况下,命令将在两个通道中传播。
关于从线程安全上下文中调用此函数的说明
通常,当您从实现模块命令的回调函数或 Redis 模块 API 提供的任何其他回调函数中调用此函数时,Redis 会将对该函数的所有调用累积到回调函数的上下文中,并会将所有命令包装在 MULTI/EXEC 事务中进行传播。但是,当从线程安全上下文中调用此函数时,该上下文可以存在不确定的时间,并且可以随时进行锁定/解锁,重要的是要注意,此 API 不是线程安全的,必须在持有 GIL 的情况下执行。
返回值
如果格式说明符无效或命令名称不属于已知命令,则命令返回 REDISMODULE_ERR
。
RedisModule_ReplicateVerbatim
int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx);
自版本 4.0.0
此函数将完全按照客户端调用的方式复制命令。请注意,复制的命令始终被包装在一个 MULTI/EXEC 中,该 MULTI/EXEC 包含在给定的模块命令执行中复制的所有命令,按执行顺序排列。
基本上,这种复制形式在您希望将命令传播到从服务器和 AOF 文件,使其与调用时的方式完全一致时很有用,因为命令可以重新执行以确定性地重新创建从旧状态开始的新状态。
重要的是要注意,此 API 不是线程安全的,必须在持有 GIL 的情况下执行。
该函数始终返回REDISMODULE_OK
。
DB 和键 API - 通用 API
RedisModule_GetClientId
unsigned long long RedisModule_GetClientId(RedisModuleCtx *ctx);
自版本 4.0.0
返回当前调用当前活动模块命令的客户端的 ID。返回的 ID 有一些保证
- 每个不同的客户端都有不同的 ID,因此,如果同一个客户端多次执行模块命令,则可以识别为具有相同的 ID,否则 ID 将不同。
- ID 呈单调递增。稍后连接到服务器的客户端保证获得的 ID 大于以前看到的任何过去 ID。
有效的 ID 范围为 1 到 2^64 - 1。如果返回 0,则表示无法在当前调用函数的上下文中获取 ID。
获取 ID 后,可以使用此宏检查命令执行是否实际上是在 AOF 加载的上下文中发生的
if (RedisModule_IsAOFClient(RedisModule_GetClientId(ctx)) {
// Handle it differently.
}
RedisModule_GetClientUserNameById
RedisModuleString *RedisModule_GetClientUserNameById(RedisModuleCtx *ctx,
uint64_t id);
自版本 6.2.1
返回使用指定客户端 ID 的客户端使用的 ACL 用户名。客户端 ID 可以使用 RedisModule_GetClientId()
API 获取。如果客户端不存在,则返回 NULL 并且 errno 设置为 ENOENT。如果客户端没有使用 ACL 用户,则返回 NULL 并且 errno 设置为 ENOTSUP
RedisModule_GetClientInfoById
int RedisModule_GetClientInfoById(void *ci, uint64_t id);
自版本 6.0.0
返回有关指定 ID 客户端的信息(该 ID 是之前通过 RedisModule_GetClientId()
API 获取的)。如果客户端存在,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
。
当客户端存在且 ci
指针不为空,但指向类型为 RedisModuleClientInfoV
1 的结构时,该结构之前已使用正确的 REDISMODULE_CLIENTINFO_INITIALIZER_V1
初始化,该结构将填充以下字段
uint64_t flags; // REDISMODULE_CLIENTINFO_FLAG_*
uint64_t id; // Client ID
char addr[46]; // IPv4 or IPv6 address.
uint16_t port; // TCP port.
uint16_t db; // Selected DB.
注意:在本次调用的上下文中,客户端 ID 是无用的,因为我们已经知道,但是相同的结构可以在其他上下文中使用,在这些上下文中我们不知道客户端 ID,但返回相同结构。
标志具有以下含义
REDISMODULE_CLIENTINFO_FLAG_SSL Client using SSL connection.
REDISMODULE_CLIENTINFO_FLAG_PUBSUB Client in Pub/Sub mode.
REDISMODULE_CLIENTINFO_FLAG_BLOCKED Client blocked in command.
REDISMODULE_CLIENTINFO_FLAG_TRACKING Client with keys tracking on.
REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET Client using unix domain socket.
REDISMODULE_CLIENTINFO_FLAG_MULTI Client in MULTI state.
但是,传递 NULL 是一种仅检查客户端是否存在的方法,以防我们对任何其他信息不感兴趣。
当我们需要返回客户端信息结构时,这是正确的用法
RedisModuleClientInfo ci = REDISMODULE_CLIENTINFO_INITIALIZER;
int retval = RedisModule_GetClientInfoById(&ci,client_id);
if (retval == REDISMODULE_OK) {
printf("Address: %s\n", ci.addr);
}
RedisModule_GetClientNameById
RedisModuleString *RedisModule_GetClientNameById(RedisModuleCtx *ctx,
uint64_t id);
自版本 7.0.3
返回具有给定 ID 的客户端连接的名称。
如果客户端 ID 不存在或客户端没有与其关联的名称,则返回 NULL。
RedisModule_SetClientNameById
int RedisModule_SetClientNameById(uint64_t id, RedisModuleString *name);
自版本 7.0.3
设置具有给定 ID 的客户端的名称。这等同于客户端调用 CLIENT SETNAME name
。
成功时返回 REDISMODULE_OK
。失败时,返回 REDISMODULE_ERR
并且 errno 设置如下
- ENOENT 如果客户端不存在
- EINVAL 如果名称包含无效字符
RedisModule_PublishMessage
int RedisModule_PublishMessage(RedisModuleCtx *ctx,
RedisModuleString *channel,
RedisModuleString *message);
自版本 6.0.0
向订阅者发布消息(参见 PUBLISH 命令)。
RedisModule_PublishMessageShard
int RedisModule_PublishMessageShard(RedisModuleCtx *ctx,
RedisModuleString *channel,
RedisModuleString *message);
自版本 7.0.0
向分片订阅者发布消息(参见 SPUBLISH 命令)。
RedisModule_GetSelectedDb
int RedisModule_GetSelectedDb(RedisModuleCtx *ctx);
自版本 4.0.0
返回当前选定的 DB。
RedisModule_GetContextFlags
int RedisModule_GetContextFlags(RedisModuleCtx *ctx);
自版本 4.0.3
返回当前上下文的标志。标志提供有关当前请求上下文的的信息(客户端是 Lua 脚本还是在 MULTI 中),以及有关 Redis 实例的一般信息,即复制和持久性。
即使在上下文为空的情况下也可以调用此函数,但是在这种情况下,以下标志将不会报告
- LUA、MULTI、REPLICATED、DIRTY(有关详细信息,请参见下文)。
可用的标志及其含义
-
REDISMODULE_CTX_FLAGS_LUA
:命令在 Lua 脚本中运行 -
REDISMODULE_CTX_FLAGS_MULTI
:命令在事务中运行 -
REDISMODULE_CTX_FLAGS_REPLICATED
:命令由 MASTER 通过复制链接发送 -
REDISMODULE_CTX_FLAGS_MASTER
:Redis 实例是主服务器 -
REDISMODULE_CTX_FLAGS_SLAVE
:Redis 实例是从服务器 -
REDISMODULE_CTX_FLAGS_READONLY
:Redis 实例是只读的 -
REDISMODULE_CTX_FLAGS_CLUSTER
:Redis 实例处于集群模式 -
REDISMODULE_CTX_FLAGS_AOF
:Redis 实例启用了 AOF -
REDISMODULE_CTX_FLAGS_RDB
:实例启用了 RDB -
REDISMODULE_CTX_FLAGS_MAXMEMORY
:实例设置了 Maxmemory -
REDISMODULE_CTX_FLAGS_EVICT
:设置了 Maxmemory 并且具有可能删除键的驱逐策略 -
REDISMODULE_CTX_FLAGS_OOM
:Redis 由于 maxmemory 设置而内存不足。 -
REDISMODULE_CTX_FLAGS_OOM_WARNING
:在达到 maxmemory 水平之前,剩余内存少于 25%。 -
REDISMODULE_CTX_FLAGS_LOADING
:服务器正在加载 RDB/AOF -
REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE
:没有与主服务器的活动链接。 -
REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING
:从服务器正在尝试连接到主服务器。 -
REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING
:主服务器 -> 从服务器 RDB 传输正在进行。 -
REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE
:从服务器与其主服务器具有活动链接。这是 STALE 状态的反义词。 -
REDISMODULE_CTX_FLAGS_ACTIVE_CHILD
:当前有一些后台进程处于活动状态(RDB、AUX 或模块)。 -
REDISMODULE_CTX_FLAGS_MULTI_DIRTY
:由于脏 CAS(已修改的键),下一个 EXEC 将失败。 -
REDISMODULE_CTX_FLAGS_IS_CHILD
:Redis 当前在后台子进程中运行。 -
REDISMODULE_CTX_FLAGS_RESP3
:指示与该上下文关联的客户端正在使用 RESP3。 -
REDISMODULE_CTX_FLAGS_SERVER_STARTUP
:Redis 实例正在启动
RedisModule_AvoidReplicaTraffic
int RedisModule_AvoidReplicaTraffic(void);
自版本 6.0.0
如果客户端向服务器发送了 CLIENT PAUSE 命令,或者 Redis 集群执行了手动故障转移,从而暂停了客户端,则返回 true。当我们有一个带有从服务器的主服务器,并且想要写入而不向复制通道添加更多数据时,这很有必要,以便从服务器的复制偏移量与主服务器的复制偏移量匹配。在这种情况下,可以在没有数据丢失的情况下安全地进行主服务器故障转移。
但是,模块可以通过使用 "!" 标志调用 RedisModule_Call()
或通过调用 RedisModule_Replicate()
来生成流量,该调用在命令执行之外的上下文中进行,例如在超时回调、线程安全上下文中等等。当模块生成过多的流量时,主服务器和从服务器的偏移量将很难匹配,因为复制通道中需要发送更多数据。
因此,当此函数返回 true 时,模块可能希望尝试避免创建复制通道数据的繁重的后台工作。这对于具有后台垃圾回收任务或在定时器回调或其他定期回调中定期写入和复制这些写入的模块非常有用。
RedisModule_SelectDb
int RedisModule_SelectDb(RedisModuleCtx *ctx, int newid);
自版本 4.0.0
更改当前选定的 DB。如果 ID 超出范围,则返回错误。
请注意,即使在调用此函数的模块实现的 Redis 命令返回后,客户端也会保留当前选定的 DB。
如果模块命令希望在不同的 DB 中更改某些内容,并返回到原始 DB,则应该在返回之前调用 RedisModule_GetSelectedDb()
以恢复旧的 DB 编号。
RedisModule_KeyExists
int RedisModule_KeyExists(RedisModuleCtx *ctx, robj *keyname);
自版本 7.0.0
检查键是否存在,而不影响其最后访问时间。
这等同于使用模式 REDISMODULE_READ
| REDISMODULE_OPEN_KEY_NOTOUCH
调用 RedisModule_OpenKey
,然后检查是否返回了 NULL,如果没有,则对打开的键调用 RedisModule_CloseKey
。
RedisModule_OpenKey
RedisModuleKey *RedisModule_OpenKey(RedisModuleCtx *ctx,
robj *keyname,
int mode);
自版本 4.0.0
返回一个表示 Redis 键的句柄,以便可以使用键句柄作为参数调用其他 API 来对键执行操作。
返回值是表示键的句柄,必须使用 RedisModule_CloseKey()
关闭。
如果键不存在并且请求了 REDISMODULE_WRITE
模式,则仍然会返回句柄,因为可以在尚未存在的键(例如,在列表推送操作之后创建的键)上执行操作。如果模式只是 REDISMODULE_READ
,而键不存在,则返回 NULL。但是,在 NULL 值上调用 RedisModule_CloseKey()
和 RedisModule_KeyType()
仍然是安全的。
可以传递给 API 的模式参数下的额外标志
REDISMODULE_OPEN_KEY_NOTOUCH
- 避免在打开时触摸键的 LRU/LFU。REDISMODULE_OPEN_KEY_NONOTIFY
- 不要在键未命中时触发键空间事件。REDISMODULE_OPEN_KEY_NOSTATS
- 不要更新键空间命中/未命中计数器。REDISMODULE_OPEN_KEY_NOEXPIRE
- 避免删除延迟过期的键。REDISMODULE_OPEN_KEY_NOEFFECTS
- 避免获取键的任何影响。
RedisModule_GetOpenKeyModesAll
int RedisModule_GetOpenKeyModesAll(void);
自版本 7.2.0
返回完整的 OpenKey 模式掩码,使用返回值,模块可以检查正在使用的 redis 服务器版本是否支持某些 OpenKey 模式集。示例
int supportedMode = RedisModule_GetOpenKeyModesAll();
if (supportedMode & REDISMODULE_OPEN_KEY_NOTOUCH) {
// REDISMODULE_OPEN_KEY_NOTOUCH is supported
} else{
// REDISMODULE_OPEN_KEY_NOTOUCH is not supported
}
RedisModule_CloseKey
void RedisModule_CloseKey(RedisModuleKey *key);
自版本 4.0.0
关闭键句柄。
RedisModule_KeyType
int RedisModule_KeyType(RedisModuleKey *key);
自版本 4.0.0
返回键的类型。如果键指针为空,则返回 REDISMODULE_KEYTYPE_EMPTY
。
RedisModule_ValueLength
size_t RedisModule_ValueLength(RedisModuleKey *key);
自版本 4.0.0
返回与键关联的值的长度。对于字符串,这是字符串的长度。对于所有其他类型,是元素的数量(仅对哈希计数键)。
如果键指针为 NULL 或键为空,则返回零。
RedisModule_DeleteKey
int RedisModule_DeleteKey(RedisModuleKey *key);
自版本 4.0.0
如果键对写入开放,则将其删除,并将键设置为接受新的写入作为空键(将在需要时创建)。成功时返回 REDISMODULE_OK
。如果键没有对写入开放,则返回 REDISMODULE_ERR
。
RedisModule_UnlinkKey
int RedisModule_UnlinkKey(RedisModuleKey *key);
自版本 4.0.7
如果键对写入开放,则将其取消链接(即以非阻塞方式删除它,不会立即回收内存)并将键设置为接受新的写入作为空键(将在需要时创建)。成功时返回 REDISMODULE_OK
。如果键没有对写入开放,则返回 REDISMODULE_ERR
。
RedisModule_GetExpire
mstime_t RedisModule_GetExpire(RedisModuleKey *key);
自版本 4.0.0
返回键过期值,以剩余 TTL 的毫秒数表示。如果键没有与之关联的 TTL 或键为空,则返回 REDISMODULE_NO_EXPIRE
。
RedisModule_SetExpire
int RedisModule_SetExpire(RedisModuleKey *key, mstime_t expire);
自版本 4.0.0
为键设置新的过期时间。如果设置了特殊过期时间 REDISMODULE_NO_EXPIRE
,则如果存在过期时间,则将其取消(与 PERSIST 命令相同)。
请注意,过期时间必须以正整数提供,表示键应具有的 TTL 的毫秒数。
该函数在成功时返回 REDISMODULE_OK
,如果键没有对写入开放或为空键,则返回 REDISMODULE_ERR
。
RedisModule_GetAbsExpire
mstime_t RedisModule_GetAbsExpire(RedisModuleKey *key);
自版本 6.2.2
返回键过期值,以绝对 Unix 时间戳表示。如果键没有与之关联的 TTL 或键为空,则返回 REDISMODULE_NO_EXPIRE
。
RedisModule_SetAbsExpire
int RedisModule_SetAbsExpire(RedisModuleKey *key, mstime_t expire);
自版本 6.2.2
为键设置新的过期时间。如果设置了特殊过期时间 REDISMODULE_NO_EXPIRE
,则如果存在过期时间,则将其取消(与 PERSIST 命令相同)。
请注意,过期时间必须以正整数提供,表示键应具有的绝对 Unix 时间戳。
该函数在成功时返回 REDISMODULE_OK
,如果键没有对写入开放或为空键,则返回 REDISMODULE_ERR
。
RedisModule_ResetDataset
void RedisModule_ResetDataset(int restart_aof, int async);
自版本 6.0.0
执行与 FLUSHALL 相似的操作,并可选地启动一个新的 AOF 文件(如果已启用)如果 restart_aof
为 true,您必须确保触发此调用的命令不会传播到 AOF 文件。当 async 设置为 true 时,db 内容将由后台线程释放。
RedisModule_DbSize
unsigned long long RedisModule_DbSize(RedisModuleCtx *ctx);
自版本 6.0.0
返回当前 db 中的键数。
RedisModule_RandomKey
RedisModuleString *RedisModule_RandomKey(RedisModuleCtx *ctx);
自版本 6.0.0
返回随机键的名称,如果当前 db 为空,则返回 NULL。
RedisModule_GetKeyNameFromOptCtx
const RedisModuleString *RedisModule_GetKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);
自版本 7.0.0
返回当前正在处理的键的名称。
RedisModule_GetToKeyNameFromOptCtx
const RedisModuleString *RedisModule_GetToKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);
自版本 7.0.0
返回当前正在处理的目标键的名称。
RedisModule_GetDbIdFromOptCtx
int RedisModule_GetDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);
自版本 7.0.0
返回当前正在处理的 dbid。
RedisModule_GetToDbIdFromOptCtx
int RedisModule_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);
自版本 7.0.0
返回当前正在处理的目标 dbid。
字符串类型的键 API
另请参见 RedisModule_ValueLength()
,它返回字符串的长度。
RedisModule_StringSet
int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str);
自版本 4.0.0
如果键对写入开放,则将指定的字符串 'str' 作为键的值设置,如果存在,则删除旧值。成功时返回 REDISMODULE_OK
。如果键没有对写入开放或存在活动迭代器,则返回 REDISMODULE_ERR
。
RedisModule_StringDMA
char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode);
自版本 4.0.0
准备与键关联的字符串值以进行 DMA 访问,并返回一个指针和大小(通过引用),用户可以使用它通过指针直接访问字符串来读取或修改字符串。
'mode' 由按位 OR 连接以下标志组成
REDISMODULE_READ -- Read access
REDISMODULE_WRITE -- Write access
如果未请求 DMA 写入,则返回的指针应仅以只读方式访问。
发生错误(类型错误)时,将返回 NULL。
DMA 访问规则
-
从获得指针的那一刻起,只要我们想使用 DMA 访问来读取或修改字符串,就不要调用其他任何键写入函数。
-
每次调用
RedisModule_StringTruncate()
时,为了继续使用 DMA 访问,应再次调用RedisModule_StringDMA()
以重新获得新的指针和长度。 -
如果返回的指针不为 NULL,但长度为零,则不能触碰任何字节(字符串为空,或键本身为空),因此如果要扩展字符串,则应使用
RedisModule_StringTruncate()
调用,并稍后再次调用 StringDMA() 以获取指针。
RedisModule_StringTruncate
int RedisModule_StringTruncate(RedisModuleKey *key, size_t newlen);
自版本 4.0.0
如果键对写入开放且为字符串类型,则调整其大小,如果新长度大于旧长度,则用零字节填充。
在此调用之后,必须再次调用 RedisModule_StringDMA()
以继续使用新的指针进行 DMA 访问。
该函数在成功时返回 REDISMODULE_OK
,并在错误时返回 REDISMODULE_ERR
,即键没有对写入开放,不是字符串或请求调整大小超过 512 MB。
如果键为空,则会使用新的字符串值创建一个字符串键,除非请求的新长度值为零。
列表类型的键 API
许多列表函数通过索引访问元素。由于列表本质上是双向链表,因此通过索引访问元素通常是 O(N) 操作。但是,如果以顺序方式或使用接近的索引访问元素,则这些函数经过优化以从上一个索引处查找索引,而不是从列表的末端查找。
这使得可以使用简单的 for 循环高效地完成迭代
long n = RedisModule_ValueLength(key);
for (long i = 0; i < n; i++) {
RedisModuleString *elem = RedisModule_ListGet(key, i);
// Do stuff...
}
请注意,在使用 RedisModule_ListPop
、RedisModule_ListSet
或 RedisModule_ListInsert
修改列表之后,内部迭代器将失效,因此下次操作需要线性查找。
以任何其他方式修改列表,例如使用 RedisModule_Call()
,当键处于开放状态时,会混淆内部迭代器,如果在进行此类修改后使用键,可能会造成问题。在这种情况下,必须重新打开键。
另请参见 RedisModule_ValueLength()
,它返回列表的长度。
RedisModule_ListPush
int RedisModule_ListPush(RedisModuleKey *key,
int where,
RedisModuleString *ele);
自版本 4.0.0
将一个元素推入列表,在头部或尾部,具体取决于 'where' 参数 (REDISMODULE_LIST_HEAD
或 REDISMODULE_LIST_TAIL
)。如果键引用一个对写入开放的空键,则会创建该键。成功时,返回 REDISMODULE_OK
。失败时,返回 REDISMODULE_ERR
并且 errno
设置如下
- 如果键或 ele 为 NULL,则为 EINVAL。
- 如果键的类型不是列表,则为 ENOTSUP。
- 如果键没有对写入开放,则为 EBADF。
注意:在 Redis 7.0 之前,此函数不会设置 errno
。
RedisModule_ListPop
RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where);
自版本 4.0.0
从列表中弹出元素,并将其作为模块字符串对象返回,用户应使用 RedisModule_FreeString()
或通过启用自动内存来释放它。where
参数指定应从列表的开头还是末尾弹出元素 (REDISMODULE_LIST_HEAD
或 REDISMODULE_LIST_TAIL
)。失败时,该命令返回 NULL 并设置 errno
如下
- 如果键为 NULL,则为 EINVAL。
- 如果键为空或类型不是列表,则为 ENOTSUP。
- 如果键没有对写入开放,则为 EBADF。
注意:在 Redis 7.0 之前,此函数不会设置 errno
。
RedisModule_ListGet
RedisModuleString *RedisModule_ListGet(RedisModuleKey *key, long index);
自版本 7.0.0
返回存储在 key
中的列表中索引 index
处的元素,类似于 LINDEX 命令。应使用 RedisModule_FreeString()
或使用自动内存管理来释放该元素。
索引为零索引,因此 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
当在给定的键和索引处找不到值时,将返回 NULL 并且 errno
设置如下
- 如果键为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键没有对读取开放,则为 EBADF。
- 如果索引不是列表中的有效索引,则为 EDOM。
RedisModule_ListSet
int RedisModule_ListSet(RedisModuleKey *key,
long index,
RedisModuleString *value);
自版本 7.0.0
替换存储在 key
中的列表中索引 index
处的元素。
索引为零索引,因此 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
成功时,返回 REDISMODULE_OK
。失败时,返回 REDISMODULE_ERR
并且 errno
设置如下
- 如果键或值为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键没有对写入开放,则为 EBADF。
- 如果索引不是列表中的有效索引,则为 EDOM。
RedisModule_ListInsert
int RedisModule_ListInsert(RedisModuleKey *key,
long index,
RedisModuleString *value);
自版本 7.0.0
在给定索引处插入元素。
索引为零索引,因此 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。索引是插入元素后的元素索引。
成功时,返回 REDISMODULE_OK
。失败时,返回 REDISMODULE_ERR
并且 errno
设置如下
- 如果键或值为 NULL,则为 EINVAL。
- 如果键的类型不是列表,则为 ENOTSUP。
- 如果键没有对写入开放,则为 EBADF。
- 如果索引不是列表中的有效索引,则为 EDOM。
RedisModule_ListDelete
int RedisModule_ListDelete(RedisModuleKey *key, long index);
自版本 7.0.0
删除给定索引处的元素。索引为 0 索引。也可以使用负索引,从列表的末尾开始计数。
成功时,返回 REDISMODULE_OK
。失败时,返回 REDISMODULE_ERR
并且 errno
设置如下
- 如果键或值为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键没有对写入开放,则为 EBADF。
- 如果索引不是列表中的有效索引,则为 EDOM。
排序集类型的键 API
另请参见 RedisModule_ValueLength()
,它返回有序集合的长度。
RedisModule_ZsetAdd
int RedisModule_ZsetAdd(RedisModuleKey *key,
double score,
RedisModuleString *ele,
int *flagsptr);
自版本 4.0.0
将一个新元素添加到有序集合中,并使用指定的 'score'。如果元素已存在,则会更新分数。
如果键是对写入开放的空键,则会在值处创建一个新的有序集合。
可以通过指针将其他标志传递给该函数,这些标志既用于接收输入,也用于在函数返回时传达状态。如果未使用特殊标志,则 'flagsptr' 可以为 NULL。
输入标志是
REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score.
Do nothing otherwise. Can optionally be combined with XX.
REDISMODULE_ZADD_LT: If element exists, new score must be less than the current score.
Do nothing otherwise. Can optionally be combined with XX.
输出标志是
REDISMODULE_ZADD_ADDED: The new element was added to the sorted set.
REDISMODULE_ZADD_UPDATED: The score of the element was updated.
REDISMODULE_ZADD_NOP: No operation was performed because XX or NX flags.
成功时,该函数返回 REDISMODULE_OK
。在以下错误情况下,返回 REDISMODULE_ERR
- 键没有对写入开放。
- 键的类型错误。
- 'score' 双精度值不是数字 (NaN)。
RedisModule_ZsetIncrby
int RedisModule_ZsetIncrby(RedisModuleKey *key,
double score,
RedisModuleString *ele,
int *flagsptr,
double *newscore);
自版本 4.0.0
此函数的工作原理与 RedisModule_ZsetAdd()
完全相同,但它不是设置新的分数,而是递增现有元素的分数,或者如果元素不存在,则将其添加,假定旧分数为零。
输入和输出标志以及返回值具有完全相同的含义,唯一的区别是,即使 'score' 是有效的双精度数,但将其添加到现有分数会导致 NaN(非数字)条件,此函数也会返回 REDISMODULE_ERR
。
此函数具有一个额外的字段 'newscore',如果该字段不为 NULL,则会填充该字段,其中包含递增后元素的新分数,如果未返回错误。
RedisModule_ZsetRem
int RedisModule_ZsetRem(RedisModuleKey *key,
RedisModuleString *ele,
int *deleted);
自版本 4.0.0
从有序集合中删除指定的元素。该函数在成功时返回 REDISMODULE_OK
,并在以下任一条件下返回 REDISMODULE_ERR
- 键没有对写入开放。
- 键的类型错误。
返回值不指示元素是否真的被删除(因为它存在),只指示函数是否成功执行。
为了知道元素是否被删除,必须传递额外的参数 'deleted',该参数通过引用填充整数,并根据操作的结果将其设置为 1 或 0。如果调用者不关心是否真的删除了元素,则 'deleted' 参数可以为 NULL。
空键将通过什么也不做来正确处理。
RedisModule_ZsetScore
int RedisModule_ZsetScore(RedisModuleKey *key,
RedisModuleString *ele,
double *score);
自版本 4.0.0
成功后,检索与排序集元素“ele”关联的双倍分数,并返回REDISMODULE_OK
。否则,返回REDISMODULE_ERR
以指示以下情况之一
- 排序集中不存在元素“ele”。
- 键不是排序集。
- 键是空的开放键。
排序集迭代器键 API
RedisModule_ZsetRangeStop
void RedisModule_ZsetRangeStop(RedisModuleKey *key);
自版本 4.0.0
停止排序集迭代。
RedisModule_ZsetRangeEndReached
int RedisModule_ZsetRangeEndReached(RedisModuleKey *key);
自版本 4.0.0
返回“范围结束”标志值以指示迭代结束。
RedisModule_ZsetFirstInScoreRange
int RedisModule_ZsetFirstInScoreRange(RedisModuleKey *key,
double min,
double max,
int minex,
int maxex);
自版本 4.0.0
设置一个排序集迭代器,以查找指定范围内的第一个元素。如果迭代器初始化成功,则返回REDISMODULE_OK
,否则在以下情况下返回REDISMODULE_ERR
- 键中存储的值不是排序集,或者键为空。
范围根据两个双精度值“min”和“max”指定。两者都可以使用以下两个宏表示无穷大
REDISMODULE_POSITIVE_INFINITE
表示正无穷大值REDISMODULE_NEGATIVE_INFINITE
表示负无穷大值
如果“minex”和“maxex”参数为真,则分别设置一个范围,其中最小值和最大值分别为排他性(不包括)而不是包含性。
RedisModule_ZsetLastInScoreRange
int RedisModule_ZsetLastInScoreRange(RedisModuleKey *key,
double min,
double max,
int minex,
int maxex);
自版本 4.0.0
与RedisModule_ZsetFirstInScoreRange()
完全相同,但选择范围的最后一个元素作为迭代的起点。
RedisModule_ZsetFirstInLexRange
int RedisModule_ZsetFirstInLexRange(RedisModuleKey *key,
RedisModuleString *min,
RedisModuleString *max);
自版本 4.0.0
设置一个排序集迭代器,以查找指定词典范围内的第一个元素。如果迭代器初始化成功,则返回REDISMODULE_OK
,否则在以下情况下返回REDISMODULE_ERR
- 键中存储的值不是排序集,或者键为空。
- 词典范围“min”和“max”格式无效。
“min”和“max”应作为两个RedisModuleString
对象提供,其格式与传递给ZRANGEBYLEX命令的参数相同。该函数不拥有这些对象,因此可以在设置迭代器后尽快释放它们。
RedisModule_ZsetLastInLexRange
int RedisModule_ZsetLastInLexRange(RedisModuleKey *key,
RedisModuleString *min,
RedisModuleString *max);
自版本 4.0.0
与RedisModule_ZsetFirstInLexRange()
完全相同,但选择范围的最后一个元素作为迭代的起点。
RedisModule_ZsetRangeCurrentElement
RedisModuleString *RedisModule_ZsetRangeCurrentElement(RedisModuleKey *key,
double *score);
自版本 4.0.0
返回活动排序集迭代器的当前排序集元素,如果迭代器中指定的范围不包含任何元素,则返回NULL。
RedisModule_ZsetRangeNext
int RedisModule_ZsetRangeNext(RedisModuleKey *key);
自版本 4.0.0
转到排序集迭代器的下一个元素。如果存在下一个元素,则返回1,如果我们已经处于最新元素或范围根本不包含任何项目,则返回0。
RedisModule_ZsetRangePrev
int RedisModule_ZsetRangePrev(RedisModuleKey *key);
自版本 4.0.0
转到排序集迭代器的上一个元素。如果存在上一个元素,则返回1,如果我们已经处于第一个元素或范围根本不包含任何项目,则返回0。
哈希类型的键 API
另见RedisModule_ValueLength()
,它返回哈希中的字段数。
RedisModule_HashSet
int RedisModule_HashSet(RedisModuleKey *key, int flags, ...);
自版本 4.0.0
将指定哈希字段的字段设置为指定的值。如果键是空键并已打开以供写入,则使用空哈希值创建键,以便设置指定字段。
该函数是可变参数的,用户必须指定字段名称和值的对,两者都作为RedisModuleString
指针(除非设置了CFIELD选项,请参阅后面)。在字段/值-ptr对的末尾,必须指定NULL作为最后一个参数以指示可变参数函数中参数的结束。
将哈希argv[1]设置为值argv[2]的示例
RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],argv[2],NULL);
该函数还可以用于删除字段(如果存在),方法是将它们设置为指定的值REDISMODULE_HASH_DELETE
RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],
REDISMODULE_HASH_DELETE,NULL);
命令的行为会随着指定的标志而改变,这些标志可以设置为REDISMODULE_HASH_NONE
,如果不需要特殊行为。
REDISMODULE_HASH_NX: The operation is performed only if the field was not
already existing in the hash.
REDISMODULE_HASH_XX: The operation is performed only if the field was
already existing, so that a new value could be
associated to an existing filed, but no new fields
are created.
REDISMODULE_HASH_CFIELDS: The field names passed are null terminated C
strings instead of RedisModuleString objects.
REDISMODULE_HASH_COUNT_ALL: Include the number of inserted fields in the
returned number, in addition to the number of
updated and deleted fields. (Added in Redis
6.2.)
除非指定了NX,否则命令会用新值覆盖旧的字段值。
使用REDISMODULE_HASH_CFIELDS
时,字段名称使用普通的C字符串报告,因此例如,要删除字段“foo”,可以使用以下代码
RedisModule_HashSet(key,REDISMODULE_HASH_CFIELDS,"foo",
REDISMODULE_HASH_DELETE,NULL);
返回值
调用之前在哈希中存在的字段数量,这些字段已更新(其旧值已替换为新值)或已删除。如果设置了标志REDISMODULE_HASH_COUNT_ALL
,则还将计算之前不存在于哈希中的插入字段。
如果返回值为零,则errno
将(从Redis 6.2开始)设置为以下值
- 如果设置了任何未知标志或键为NULL,则为EINVAL。
- 如果键与非哈希值关联,则为ENOTSUP。
- 如果键未打开以供写入,则为EBADF。
- 如果如上所述返回值中没有计算任何字段,则为ENOENT。这实际上不是错误。如果所有字段都刚刚创建且未设置
COUNT_ALL
标志,或者由于NX和XX标志而导致更改被抑制,则返回值可以为零。
注意:此函数的返回值语义在Redis 6.2和更早版本之间有很大不同。使用它的模块应确定Redis版本并相应地进行处理。
RedisModule_HashGet
int RedisModule_HashGet(RedisModuleKey *key, int flags, ...);
自版本 4.0.0
从哈希值中获取字段。此函数使用可变数量的参数调用,交替使用字段名称(作为RedisModuleString
指针)和指向RedisModuleString
指针的指针,该指针在字段存在时设置为字段的值,或者在字段不存在时设置为NULL。在字段/值-ptr对的末尾,必须指定NULL作为最后一个参数以指示可变参数函数中参数的结束。
这是一个使用示例
RedisModuleString *first, *second;
RedisModule_HashGet(mykey,REDISMODULE_HASH_NONE,argv[1],&first,
argv[2],&second,NULL);
与RedisModule_HashSet()
一样,可以通过传递与REDISMODULE_HASH_NONE
不同的标志来指定命令的行为
REDISMODULE_HASH_CFIELDS
:以空终止的C字符串表示的字段名称。
REDISMODULE_HASH_EXISTS
:该函数不是设置期望指向RedisModuleString
指针的指针的字段的值,而是只报告字段是否存在,并期望每个对的第二个元素为一个整数指针。
REDISMODULE_HASH_CFIELDS
的示例
RedisModuleString *username, *hashedpass;
RedisModule_HashGet(mykey,REDISMODULE_HASH_CFIELDS,"username",&username,"hp",&hashedpass, NULL);
REDISMODULE_HASH_EXISTS
的示例
int exists;
RedisModule_HashGet(mykey,REDISMODULE_HASH_EXISTS,argv[1],&exists,NULL);
如果成功,该函数返回REDISMODULE_OK
,如果键不是哈希值,则返回REDISMODULE_ERR
。
内存管理
返回的RedisModuleString
对象应使用RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
流类型的键 API
有关流的介绍,请参阅https://redis.ac.cn/topics/streams-intro。
类型RedisModuleStreamID
用于流函数,它是一个具有两个64位字段的结构,定义为
typedef struct RedisModuleStreamID {
uint64_t ms;
uint64_t seq;
} RedisModuleStreamID;
另见RedisModule_ValueLength()
,它返回流的长度,以及转换函数RedisModule_StringToStreamID()
和RedisModule_CreateStringFromStreamID()
。
RedisModule_StreamAdd
int RedisModule_StreamAdd(RedisModuleKey *key,
int flags,
RedisModuleStreamID *id,
RedisModuleString **argv,
long numfields);
自版本 6.2.0
将条目添加到流中。与没有修剪的XADD相同。
key
:存储流的键(或将要存储的键)flags
:一个位字段REDISMODULE_STREAM_ADD_AUTOID
:自动分配流ID,就像XADD命令中的“*”一样。
id
:如果设置了AUTOID
标志,则这是分配的ID返回的位置。如果设置了AUTOID
,可以为NULL,如果您不关心接收ID。如果未设置AUTOID
,则这是请求的ID。argv
:指向大小为numfields * 2
的数组的指针,该数组包含字段和值。numfields
:argv
中的字段-值对数量。
如果已添加条目,则返回REDISMODULE_OK
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- 如果使用无效参数调用,则为EINVAL
- 如果键引用的是除流之外的类型的值,则为ENOTSUP
- 如果键未打开以供写入,则为EBADF
- 如果给定的ID为0-0或不超过流中所有其他ID(仅当未设置AUTOID标志时)则为EDOM
- 如果流已达到最后可能的ID,则为EFBIG
- 如果元素太大而无法存储,则为ERANGE。
RedisModule_StreamDelete
int RedisModule_StreamDelete(RedisModuleKey *key, RedisModuleStreamID *id);
自版本 6.2.0
从流中删除条目。
key
:已打开以供写入的键,没有启动流迭代器。id
:要删除的条目的流ID。
如果成功,则返回REDISMODULE_OK
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- 如果使用无效参数调用,则为EINVAL
- 如果键引用的是除流之外的类型的值,或者键为空,则为ENOTSUP
- 如果键未打开以供写入,或者键与流迭代器关联,则为EBADF
- 如果不存在具有给定流ID的条目,则为ENOENT
另见RedisModule_StreamIteratorDelete()
,用于在使用流迭代器迭代时删除当前条目。
RedisModule_StreamIteratorStart
int RedisModule_StreamIteratorStart(RedisModuleKey *key,
int flags,
RedisModuleStreamID *start,
RedisModuleStreamID *end);
自版本 6.2.0
设置流迭代器。
key
:使用RedisModule_OpenKey()
打开以供读取的流键。flags
:REDISMODULE_STREAM_ITERATOR_EXCLUSIVE
:不要将start
和end
包括在迭代的范围内。REDISMODULE_STREAM_ITERATOR_REVERSE
:以相反的顺序迭代,从范围的end
开始。
start
:范围的下限。对流的开头使用NULL。end
:范围的上限。对流的末尾使用NULL。
如果成功,则返回REDISMODULE_OK
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- 如果使用无效参数调用,则为EINVAL
- 如果键引用的是除流之外的类型的值,或者键为空,则为ENOTSUP
- EBADF如果键未打开以供写入,或者键已与流迭代器关联
- EDOM如果
start
或end
超出有效范围
如果成功,则返回REDISMODULE_OK
,如果键不引用流或给出了无效参数,则返回REDISMODULE_ERR
。
流ID使用RedisModule_StreamIteratorNextID()
检索,对于每个流ID,使用RedisModule_StreamIteratorNextField()
检索字段和值。通过调用RedisModule_StreamIteratorStop()
来释放迭代器。
示例(错误处理省略)
RedisModule_StreamIteratorStart(key, 0, startid_ptr, endid_ptr);
RedisModuleStreamID id;
long numfields;
while (RedisModule_StreamIteratorNextID(key, &id, &numfields) ==
REDISMODULE_OK) {
RedisModuleString *field, *value;
while (RedisModule_StreamIteratorNextField(key, &field, &value) ==
REDISMODULE_OK) {
//
// ... Do stuff ...
//
RedisModule_FreeString(ctx, field);
RedisModule_FreeString(ctx, value);
}
}
RedisModule_StreamIteratorStop(key);
RedisModule_StreamIteratorStop
int RedisModule_StreamIteratorStop(RedisModuleKey *key);
自版本 6.2.0
停止使用RedisModule_StreamIteratorStart()
创建的流迭代器并回收其内存。
如果成功,则返回REDISMODULE_OK
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- EINVAL如果使用NULL键调用
- 如果键引用的是除流之外的类型的值,或者键为空,则为ENOTSUP
- EBADF如果键未打开以供写入,或者没有流迭代器与键关联
RedisModule_StreamIteratorNextID
int RedisModule_StreamIteratorNextID(RedisModuleKey *key,
RedisModuleStreamID *id,
long *numfields);
自版本 6.2.0
查找下一个流条目并返回其流ID和字段数。
key
:已使用RedisModule_StreamIteratorStart()
为其启动了流迭代器的键。id
:返回的流ID。如果您不关心,则为NULL。numfields
:找到的流条目中的字段数。如果您不关心,则为NULL。
如果找到条目,则返回REDISMODULE_OK
并设置*id
和*numfields
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- EINVAL如果使用NULL键调用
- 如果键引用的是除流之外的类型的值,或者键为空,则为ENOTSUP
- EBADF如果键没有与之关联的流迭代器
- ENOENT如果迭代器范围内没有更多条目
实际上,如果在成功调用RedisModule_StreamIteratorStart()
之后,并使用相同的键调用RedisModule_StreamIteratorNextID()
,则可以安全地假设REDISMODULE_ERR
返回值意味着没有更多条目。
使用RedisModule_StreamIteratorNextField()
检索字段和值。请参阅RedisModule_StreamIteratorStart()
处的示例。
RedisModule_StreamIteratorNextField
int RedisModule_StreamIteratorNextField(RedisModuleKey *key,
RedisModuleString **field_ptr,
RedisModuleString **value_ptr);
自版本 6.2.0
在流迭代中检索当前流 ID 的下一个字段及其对应值。在调用 RedisModule_StreamIteratorNextID()
获取每个字段值对后,应反复调用此函数。
key
: 已启动流迭代器的键。field_ptr
: 此处返回字段。value_ptr
: 此处返回值。
返回 REDISMODULE_OK
并将 *field_ptr
和 *value_ptr
指向新分配的 RedisModuleString
对象。如果启用了自动内存,则在回调完成时会自动释放字符串对象。如果失败,则返回 REDISMODULE_ERR
,并根据以下情况设置 errno
- EINVAL如果使用NULL键调用
- 如果键引用的是除流之外的类型的值,或者键为空,则为ENOTSUP
- EBADF如果键没有与之关联的流迭代器
- 如果当前流条目中没有更多字段,则为 ENOENT
实际上,如果在成功调用 RedisModule_StreamIteratorNextID()
之后并使用相同的键调用 RedisModule_StreamIteratorNextField()
,则可以安全地假设 REDISMODULE_ERR
返回值意味着没有更多字段。
请参阅 RedisModule_StreamIteratorStart()
中的示例。
RedisModule_StreamIteratorDelete
int RedisModule_StreamIteratorDelete(RedisModuleKey *key);
自版本 6.2.0
在迭代时删除当前流条目。
此函数可以在 RedisModule_StreamIteratorNextID()
之后或在任何 RedisModule_StreamIteratorNextField()
调用之后调用。
如果成功,则返回REDISMODULE_OK
。如果失败,则返回REDISMODULE_ERR
,并设置errno
,如下所示
- 如果 key 为 NULL,则为 EINVAL
- 如果 key 为空或类型不是流,则为 ENOTSUP
- 如果 key 未打开写入,或未启动迭代器,则为 EBADF
- 如果迭代器没有当前流条目,则为 ENOENT
RedisModule_StreamTrimByLength
long long RedisModule_StreamTrimByLength(RedisModuleKey *key,
int flags,
long long length);
自版本 6.2.0
按长度修剪流,类似于 XTRIM 使用 MAXLEN。
key
: 打开写入的键。flags
: 位字段,包含REDISMODULE_STREAM_TRIM_APPROX
: 如果提高性能,则修剪更少,类似于 XTRIM 使用~
。
length
: 修剪后要保留的流条目数。
返回删除的条目数。如果失败,则返回负值,并根据以下情况设置 errno
- 如果使用无效参数调用,则为EINVAL
- 如果 key 为空或类型不是流,则为 ENOTSUP
- 如果 key 未打开写入,则为 EBADF
RedisModule_StreamTrimByID
long long RedisModule_StreamTrimByID(RedisModuleKey *key,
int flags,
RedisModuleStreamID *id);
自版本 6.2.0
按 ID 修剪流,类似于 XTRIM 使用 MINID。
key
: 打开写入的键。flags
: 位字段,包含REDISMODULE_STREAM_TRIM_APPROX
: 如果提高性能,则修剪更少,类似于 XTRIM 使用~
。
id
: 修剪后要保留的最小流 ID。
返回删除的条目数。如果失败,则返回负值,并根据以下情况设置 errno
- 如果使用无效参数调用,则为EINVAL
- 如果 key 为空或类型不是流,则为 ENOTSUP
- 如果 key 未打开写入,则为 EBADF
从模块调用 Redis 命令
RedisModule_Call()
向 Redis 发送命令。其余函数处理回复。
RedisModule_FreeCallReply
void RedisModule_FreeCallReply(RedisModuleCallReply *reply);
自版本 4.0.0
释放调用回复及其包含的所有嵌套回复(如果它是数组)。
RedisModule_CallReplyType
int RedisModule_CallReplyType(RedisModuleCallReply *reply);
自版本 4.0.0
将回复类型返回为以下类型之一
REDISMODULE_REPLY_UNKNOWN
REDISMODULE_REPLY_STRING
REDISMODULE_REPLY_ERROR
REDISMODULE_REPLY_INTEGER
REDISMODULE_REPLY_ARRAY
REDISMODULE_REPLY_NULL
REDISMODULE_REPLY_MAP
REDISMODULE_REPLY_SET
REDISMODULE_REPLY_BOOL
REDISMODULE_REPLY_DOUBLE
REDISMODULE_REPLY_BIG_NUMBER
REDISMODULE_REPLY_VERBATIM_STRING
REDISMODULE_REPLY_ATTRIBUTE
REDISMODULE_REPLY_PROMISE
RedisModule_CallReplyLength
size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply);
自版本 4.0.0
返回回复类型的长度(如果适用)。
RedisModule_CallReplyArrayElement
RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply,
size_t idx);
自版本 4.0.0
返回数组回复的第 'idx' 个嵌套调用回复元素,如果回复类型不正确或索引超出范围,则返回 NULL。
RedisModule_CallReplyInteger
long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply);
自版本 4.0.0
返回整数回复的 long long
值。
RedisModule_CallReplyDouble
double RedisModule_CallReplyDouble(RedisModuleCallReply *reply);
自版本 7.0.0
返回双精度回复的双精度值。
RedisModule_CallReplyBigNumber
const char *RedisModule_CallReplyBigNumber(RedisModuleCallReply *reply,
size_t *len);
自版本 7.0.0
返回大数字回复的大数字值。
RedisModule_CallReplyVerbatim
const char *RedisModule_CallReplyVerbatim(RedisModuleCallReply *reply,
size_t *len,
const char **format);
自版本 7.0.0
返回逐字字符串回复的值。可以提供一个可选的输出参数来获取逐字回复格式。
RedisModule_CallReplyBool
int RedisModule_CallReplyBool(RedisModuleCallReply *reply);
自版本 7.0.0
返回布尔回复的布尔值。
RedisModule_CallReplySetElement
RedisModuleCallReply *RedisModule_CallReplySetElement(RedisModuleCallReply *reply,
size_t idx);
自版本 7.0.0
返回集合回复的第 'idx' 个嵌套调用回复元素,如果回复类型不正确或索引超出范围,则返回 NULL。
RedisModule_CallReplyMapElement
int RedisModule_CallReplyMapElement(RedisModuleCallReply *reply,
size_t idx,
RedisModuleCallReply **key,
RedisModuleCallReply **val);
自版本 7.0.0
检索映射回复的第 'idx' 个键和值。
返回值
- 成功时返回
REDISMODULE_OK
。 - 如果 idx 超出范围或回复类型不正确,则为
REDISMODULE_ERR
。
key
和 value
参数用于通过引用返回,如果不需要,可以为 NULL。
RedisModule_CallReplyAttribute
RedisModuleCallReply *RedisModule_CallReplyAttribute(RedisModuleCallReply *reply);
自版本 7.0.0
返回给定回复的属性,如果不存在属性,则返回 NULL。
RedisModule_CallReplyAttributeElement
int RedisModule_CallReplyAttributeElement(RedisModuleCallReply *reply,
size_t idx,
RedisModuleCallReply **key,
RedisModuleCallReply **val);
自版本 7.0.0
检索属性回复的第 'idx' 个键和值。
返回值
- 成功时返回
REDISMODULE_OK
。 - 如果 idx 超出范围或回复类型不正确,则为
REDISMODULE_ERR
。
key
和 value
参数用于通过引用返回,如果不需要,可以为 NULL。
RedisModule_CallReplyPromiseSetUnblockHandler
void RedisModule_CallReplyPromiseSetUnblockHandler(RedisModuleCallReply *reply,
RedisModuleOnUnblocked on_unblock,
void *private_data);
自版本 7.2.0
在给定的 promise RedisModuleCallReply
上设置解除阻塞处理程序(回调和私有数据)。给定的回复必须是 promise 类型(REDISMODULE_REPLY_PROMISE
)。
RedisModule_CallReplyPromiseAbort
int RedisModule_CallReplyPromiseAbort(RedisModuleCallReply *reply,
void **private_data);
自版本 7.2.0
中止给定的 promise RedisModuleCallReply
的执行。如果中止成功,则返回 REDMODULE_OK
,如果无法中止执行(执行已完成),则返回 REDISMODULE_ERR
。如果执行已中止(返回 REDMODULE_OK
),则 private_data
输出参数将设置为在 'RedisModule_CallReplyPromiseSetUnblockHandler
' 中提供的私有数据的 value,以便调用者能够释放私有数据。
如果执行已成功中止,则保证解除阻塞处理程序不会被调用。也就是说,中止操作可能会成功,但操作仍会继续。例如,如果模块实现了一些阻塞命令且不尊重断开连接回调,则可能会发生这种情况。对于纯 Redis 命令,这种情况不会发生。
RedisModule_CallReplyStringPtr
const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply,
size_t *len);
自版本 4.0.0
返回字符串或错误回复的指针和长度。
RedisModule_CreateStringFromCallReply
RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply);
自版本 4.0.0
从类型为字符串、错误或整数的调用回复返回一个新的字符串对象。否则(回复类型错误)返回 NULL。
RedisModule_SetContextUser
void RedisModule_SetContextUser(RedisModuleCtx *ctx,
const RedisModuleUser *user);
自版本 7.0.6
修改 RedisModule_Call
将使用的用户(例如,用于 ACL 检查)。
RedisModule_Call
RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx,
const char *cmdname,
const char *fmt,
...);
自版本 4.0.0
从模块中调用任何 Redis 命令的导出 API。
-
cmdname: 要调用的 Redis 命令。
-
fmt: 命令参数的格式说明符字符串。每个参数都应该由有效的类型说明符指定。格式说明符还可以包含修饰符
!
、A
、3
和R
,这些修饰符没有对应的参数。-
b
-- 参数是一个缓冲区,紧随其后是另一个参数,它是缓冲区的长度。 -
c
-- 参数是指向普通 C 字符串(以 null 结尾)的指针。 -
l
-- 参数是long long
整数。 -
s
-- 参数是 RedisModuleString。 -
v
-- 参数是 RedisModuleString 的向量。 -
!
-- 将 Redis 命令及其参数发送到副本和 AOF。 -
A
-- 禁止 AOF 传播,仅发送到副本(需要!
)。 -
R
-- 禁止副本传播,仅发送到 AOF(需要!
)。 -
3
-- 返回 RESP3 回复。这将改变命令回复。例如,HGETALL 返回一个映射,而不是一个扁平的数组。 -
0
-- 以自动模式返回回复,即回复格式将与附加到给定 RedisModuleCtx 的客户端相同。当您想要将回复直接传递给客户端时,这可能会用到。 -
C
-- 以附加到上下文的用户的身份运行命令。用户可以通过直接发出命令并创建上下文的客户端或通过 RedisModule_SetContextUser 自动附加。如果上下文不是由已发出的命令直接创建的(例如,后台上下文且未通过 RedisModule_SetContextUser 在其上设置用户,则 RedisModule_Call 会失败。检查命令是否可以根据 ACL 规则执行,并使命令以确定的用户的身份运行,以便任何未来的用户依赖性活动(例如,脚本中的 ACL 检查)按预期进行。否则,命令将以 Redis 无限制用户身份运行。 -
S
-- 以脚本模式运行命令,这意味着如果调用了在脚本中不允许的命令(带有deny-script
标记,例如 SHUTDOWN),它将引发错误。此外,在脚本模式下,如果副本数量不足(如min-replicas-to-write
配置),或者服务器无法持久保存到磁盘,则不允许使用写入命令。 -
W
-- 不允许运行任何写入命令(带有write
标记)。 -
M
-- 超出内存限制时,不允许使用deny-oom
标记的命令。 -
E
-- 以 RedisModuleCallReply 的形式返回错误。如果在调用命令之前发生错误,则使用 errno 机制返回错误。此标志允许以错误 CallReply 的形式获取错误,并提供相关的错误消息。 -
'D' -- “干运行”模式。在执行底层调用() 之前返回。如果一切顺利,它将返回 NULL,否则它将返回一个 CallReply 对象,表示错误,就像使用 'E' 代码调用一样。
-
'K' -- 允许运行阻塞命令。如果启用此功能,并且命令被阻塞,则会返回一个特殊的 REDISMODULE_REPLY_PROMISE。此回复类型表示命令已阻塞,并且回复将异步提供。模块可以使用此回复对象设置一个处理程序,该处理程序将在使用 RedisModule_CallReplyPromiseSetUnblockHandler 解除命令阻塞时被调用。必须在命令调用后立即设置处理程序(在释放 Redis 锁之前)。如果没有设置处理程序,阻塞的 RedisModule_Call 将继续执行,但回复将被忽略(触发并忘记),请注意,在角色更改的情况下,这样做很危险,如下所述。模块可以使用 RedisModule_CallReplyPromiseAbort 中止命令调用(如果尚未完成,请参阅 RedisModule_CallReplyPromiseAbort 文档以了解更多详细信息)。模块还负责在角色更改时中止执行,可以通过使用服务器事件(在实例变为副本时收到通知)或依赖于原始客户端的断开连接回调来实现。如果未能这样做,可能会导致在副本上执行写入操作。与其他调用回复不同,promise 调用回复必须在 Redis GIL 被锁定时释放。请注意,在解除阻塞时,唯一的承诺是将调用解除阻塞处理程序。如果阻塞的 RedisModule_Call 使模块也阻塞了一些真实的客户端(使用 RedisModule_BlockClient),则模块负责在解除阻塞处理程序中解除阻塞该客户端。在解除阻塞处理程序中,只允许执行以下操作:* 使用 RedisModule_Call 调用其他 Redis 命令* 使用 RedisModule_OpenKey 打开键* 将数据复制到副本或 AOF
Specifically, it is not allowed to call any Redis module API which are client related such as: * RedisModule_Reply* API's * RedisModule_BlockClient * RedisModule_GetCurrentUserName
-
-
...: Redis 命令的实际参数。
如果成功,则返回 RedisModuleCallReply
对象,否则返回 NULL,并将 errno 设置为以下值
- EBADF: 格式说明符错误。
- EINVAL: 命令元数错误。
- ENOENT: 命令不存在。
- EPERM: 在集群实例中操作,键位于非本地槽中。
- EROFS: 在集群实例中操作,在只读状态下发送写入命令。
- ENETDOWN: 在集群实例中操作,集群已关闭。
- ENOTSUP: 指定的模块上下文没有 ACL 用户。
- EACCES: 根据 ACL 规则,无法执行命令。
- ENOSPC: 不允许写入或
deny-oom
命令。 - ESPIPE: 脚本模式下不允许使用命令。
示例代码片段
reply = RedisModule_Call(ctx,"INCRBY","sc",argv[1],"10");
if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {
long long myval = RedisModule_CallReplyInteger(reply);
// Do something with myval.
}
此 API 在此处记录:https://redis.ac.cn/topics/modules-intro
RedisModule_CallReplyProto
const char *RedisModule_CallReplyProto(RedisModuleCallReply *reply,
size_t *len);
自版本 4.0.0
返回由返回回复对象的命令返回的协议的指针和长度。
模块数据类型
当字符串 DMA 或使用现有数据结构不足时,可以从头开始创建新的数据类型并将其导出到 Redis。 模块必须提供一组回调函数来处理导出的新值(例如,为了提供 RDB 保存/加载、AOF 重写等)。 在本节中,我们将定义此 API。
RedisModule_CreateDataType
moduleType *RedisModule_CreateDataType(RedisModuleCtx *ctx,
const char *name,
int encver,
void *typemethods_ptr);
自版本 4.0.0
注册模块导出的新数据类型。 参数如下。 有关深入的文档,请查看模块 API 文档,尤其是 https://redis.ac.cn/docs/latest/develop/reference/modules/modules-native-types/。
-
name: 9 个字符的数据类型名称,在 Redis 模块生态系统中必须唯一。 发挥创意... 这样就不会发生冲突。 使用字符集 A-Z a-z 9-0,加上两个 "-_" 字符。 一个好主意是使用,例如
<typename>-<vendor>
。 例如“tree-AntZ”可能意味着“@antirez 的树数据结构”。 使用小写和大写字母都有助于防止冲突。 -
encver: 编码版本,即模块用于持久化数据的序列化版本。 只要“name”匹配,RDB 加载将被分派到类型回调函数,无论使用什么 'encver',但模块可以理解它必须加载的编码是否来自模块的旧版本。 例如,模块“tree-AntZ”最初使用 encver=0。 后来升级后,它开始以不同的格式序列化数据,并使用 encver=1 注册类型。 但是,如果
rdb_load
回调函数能够检查 encver 值并相应地采取行动,该模块仍然可以加载由旧版本产生的旧数据。 encver 必须是介于 0 到 1023 之间的正值。 -
typemethods_ptr 是指向
RedisModuleTypeMethods
结构体的指针,该结构体应填充方法回调和结构体版本,如下面的示例所示RedisModuleTypeMethods tm = { .version = REDISMODULE_TYPE_METHOD_VERSION, .rdb_load = myType_RDBLoadCallBack, .rdb_save = myType_RDBSaveCallBack, .aof_rewrite = myType_AOFRewriteCallBack, .free = myType_FreeCallBack, // Optional fields .digest = myType_DigestCallBack, .mem_usage = myType_MemUsageCallBack, .aux_load = myType_AuxRDBLoadCallBack, .aux_save = myType_AuxRDBSaveCallBack, .free_effort = myType_FreeEffortCallBack, .unlink = myType_UnlinkCallBack, .copy = myType_CopyCallback, .defrag = myType_DefragCallback // Enhanced optional fields .mem_usage2 = myType_MemUsageCallBack2, .free_effort2 = myType_FreeEffortCallBack2, .unlink2 = myType_UnlinkCallBack2, .copy2 = myType_CopyCallback2, }
-
rdb_load: 用于从 RDB 文件加载数据的回调函数指针。
-
rdb_save: 用于将数据保存到 RDB 文件的回调函数指针。
-
aof_rewrite: 用于将数据重写为命令的回调函数指针。
-
digest: 用于
DEBUG DIGEST
的回调函数指针。 -
free: 可以释放类型值的回调函数指针。
-
aux_save: 用于将键空间外数据保存到 RDB 文件的回调函数指针。 'when' 参数可以是
REDISMODULE_AUX_BEFORE_RDB
或REDISMODULE_AUX_AFTER_RDB
。 -
aux_load: 用于从 RDB 文件加载键空间外数据的回调函数指针。 与
aux_save
类似,成功时返回REDISMODULE_OK
,否则返回 ERR。 -
free_effort: 用于确定模块内存是否需要延迟回收的回调函数指针。 模块应返回释放值所涉及的复杂度。 例如:要释放多少个指针。 请注意,如果它返回 0,我们将始终执行异步释放。
-
unlink: 用于通知模块 Redis 已从 DB 中删除该键,并且可能很快会被后台线程释放的回调函数指针。 请注意,它不会在 FLUSHALL/FLUSHDB(同步和异步)上调用,并且模块可以使用
RedisModuleEvent_FlushDB
来挂钩到该操作。 -
copy: 用于制作指定键副本的回调函数指针。 模块应执行指定值的深层副本并将其返回。 此外,还提供了有关源键和目标键名称的提示。 NULL 返回值被认为是错误,复制操作失败。 注意:如果目标键存在且正在被覆盖,则将首先调用复制回调函数,然后调用要替换的值的释放回调函数。
-
defrag: 用于请求模块对键进行碎片整理的回调函数指针。 然后,模块应迭代指针并调用相关的
RedisModule_Defrag*()
函数来对指针或复杂类型进行碎片整理。 模块应继续迭代,只要RedisModule_DefragShouldStop()
返回零值,并在完成时返回零值,或者在还有更多工作要完成时返回非零值。 如果还有更多工作需要完成,可以使用RedisModule_DefragCursorSet()
和RedisModule_DefragCursorGet()
来跟踪跨不同调用的这项工作。 通常,碎片整理机制会无时间限制地调用回调函数,因此RedisModule_DefragShouldStop()
始终返回零。 具有时间限制并提供游标支持的“延迟碎片整理”机制仅用于确定具有显着内部复杂度的键。 为了确定这一点,碎片整理机制使用free_effort
回调函数和“active-defrag-max-scan-fields”配置指令。 注意:该值作为void**
传递,并且该函数应在顶层值指针被碎片整理并因此发生更改时更新该指针。 -
mem_usage2: 与
mem_usage
相似,但提供RedisModuleKeyOptCtx
参数,以便可以获取元信息(如键名称和 DB ID),以及用于大小估计的sample_size
(参见 MEMORY USAGE 命令)。 -
free_effort2: 与
free_effort
相似,但提供RedisModuleKeyOptCtx
参数,以便可以获取元信息(如键名称和 DB ID)。 -
unlink2: 与
unlink
相似,但提供RedisModuleKeyOptCtx
参数,以便可以获取元信息(如键名称和 DB ID)。 -
copy2: 与
copy
相似,但提供RedisModuleKeyOptCtx
参数,以便可以获取元信息(如键名称和 DB ID)。 -
aux_save2: 与
aux_save
相似,但语义略有变化,如果模块在此回调函数上不保存任何内容,则不会将有关此 aux 字段的任何数据写入 RDB,即使未加载模块,也可以加载 RDB。
注意:模块名称“AAAAAAAAA”是保留的,会导致错误,它也相当糟糕。
如果在 RedisModule_OnLoad()
函数之外调用 RedisModule_CreateDataType()
,则已经存在一个模块注册了具有相同名称的类型,或者如果模块名称或 encver 无效,则返回 NULL。 否则,新类型将注册到 Redis,并返回类型为 RedisModuleType
的引用:函数的调用者应将此引用存储到全局变量中,以便将来在模块类型 API 中使用,因为单个模块可以注册多个类型。 示例代码片段
static RedisModuleType *BalancedTreeType;
int RedisModule_OnLoad(RedisModuleCtx *ctx) {
// some code here ...
BalancedTreeType = RedisModule_CreateDataType(...);
}
RedisModule_ModuleTypeSetValue
int RedisModule_ModuleTypeSetValue(RedisModuleKey *key,
moduleType *mt,
void *value);
自版本 4.0.0
如果键对写入开放,则将指定模块类型对象设置为键的值,如果存在旧值,则删除旧值。 成功时返回 REDISMODULE_OK
。 如果键对写入不开放或存在活动迭代器,则返回 REDISMODULE_ERR
。
RedisModule_ModuleTypeGetType
moduleType *RedisModule_ModuleTypeGetType(RedisModuleKey *key);
自版本 4.0.0
假设 RedisModule_KeyType()
在该键上返回 REDISMODULE_KEYTYPE_MODULE
,则返回存储在该键处的模块类型指针。
如果键为 NULL,不与模块类型关联,或为空,则返回 NULL。
RedisModule_ModuleTypeGetValue
void *RedisModule_ModuleTypeGetValue(RedisModuleKey *key);
自版本 4.0.0
假设 RedisModule_KeyType()
在该键上返回 REDISMODULE_KEYTYPE_MODULE
,则返回存储在该键处的模块类型低级值,与用户通过 RedisModule_ModuleTypeSetValue()
设置的值相同。
如果键为 NULL,不与模块类型关联,或为空,则返回 NULL。
RDB 加载和保存函数
RedisModule_IsIOError
int RedisModule_IsIOError(RedisModuleIO *io);
自版本 6.0.0
如果任何先前的 IO API 失败,则返回 true。 对于 Load*
API,REDISMODULE_OPTIONS_HANDLE_IO_ERRORS
标志必须先使用 RedisModule_SetModuleOptions
设置。
RedisModule_SaveUnsigned
void RedisModule_SaveUnsigned(RedisModuleIO *io, uint64_t value);
自版本 4.0.0
将无符号 64 位值保存到 RDB 文件中。 此函数只能在模块实现新数据类型的 rdb_save
方法的上下文中调用。
RedisModule_LoadUnsigned
uint64_t RedisModule_LoadUnsigned(RedisModuleIO *io);
自版本 4.0.0
从 RDB 文件中加载无符号 64 位值。 此函数只能在模块实现新数据类型的 rdb_load
方法的上下文中调用。
RedisModule_SaveSigned
void RedisModule_SaveSigned(RedisModuleIO *io, int64_t value);
自版本 4.0.0
与 RedisModule_SaveUnsigned()
相似,但适用于有符号 64 位值。
RedisModule_LoadSigned
int64_t RedisModule_LoadSigned(RedisModuleIO *io);
自版本 4.0.0
与 RedisModule_LoadUnsigned()
相似,但适用于有符号 64 位值。
RedisModule_SaveString
void RedisModule_SaveString(RedisModuleIO *io, RedisModuleString *s);
自版本 4.0.0
在模块类型的 rdb_save
方法的上下文中,将字符串保存到 RDB 文件中,并将 RedisModuleString
作为输入。
该字符串随后可以使用 RedisModule_LoadString()
或其他期望 RDB 文件中序列化字符串的 Load 系列函数加载。
RedisModule_SaveStringBuffer
void RedisModule_SaveStringBuffer(RedisModuleIO *io,
const char *str,
size_t len);
自版本 4.0.0
与 RedisModule_SaveString()
相似,但将原始 C 指针和长度作为输入。
RedisModule_LoadString
RedisModuleString *RedisModule_LoadString(RedisModuleIO *io);
自版本 4.0.0
在模块数据类型的 rdb_load
方法的上下文中,从 RDB 文件中加载字符串,该字符串之前已使用 RedisModule_SaveString()
函数系列保存。
返回的字符串是新分配的 RedisModuleString
对象,用户应在某个时候使用对 RedisModule_FreeString()
的调用来释放它。
如果数据结构不将字符串存储为 RedisModuleString
对象,则可以使用类似的函数 RedisModule_LoadStringBuffer()
代替。
RedisModule_LoadStringBuffer
char *RedisModule_LoadStringBuffer(RedisModuleIO *io, size_t *lenptr);
自版本 4.0.0
与 RedisModule_LoadString()
相似,但返回使用 RedisModule_Alloc()
分配的堆分配字符串,可以使用 RedisModule_Realloc()
或 RedisModule_Free()
调整其大小或释放它。
如果 *lenptr 不为 NULL,则字符串的大小将存储在 *lenptr 中。 返回的字符串不会自动以 NULL 结尾,它将按照在 RDB 文件中存储时的完全相同方式加载。
RedisModule_SaveDouble
void RedisModule_SaveDouble(RedisModuleIO *io, double value);
自版本 4.0.0
在模块数据类型的 rdb_save
方法的上下文中,将 double 值保存到 RDB 文件中。 double 可以是有效数字、NaN 或无穷大。 可以使用 RedisModule_LoadDouble()
加载回该值。
RedisModule_LoadDouble
double RedisModule_LoadDouble(RedisModuleIO *io);
自版本 4.0.0
在模块数据类型的 rdb_save
方法的上下文中,加载回 RedisModule_SaveDouble()
保存的 double 值。
RedisModule_SaveFloat
void RedisModule_SaveFloat(RedisModuleIO *io, float value);
自版本 4.0.0
在模块数据类型的 rdb_save
方法的上下文中,将 float 值保存到 RDB 文件中。 float 可以是有效数字、NaN 或无穷大。 可以使用 RedisModule_LoadFloat()
加载回该值。
RedisModule_LoadFloat
float RedisModule_LoadFloat(RedisModuleIO *io);
自版本 4.0.0
在模块数据类型的 rdb_save
方法的上下文中,加载回 RedisModule_SaveFloat()
保存的 float 值。
RedisModule_SaveLongDouble
void RedisModule_SaveLongDouble(RedisModuleIO *io, long double value);
自版本 6.0.0
在模块数据类型的 rdb_save
方法的上下文中,将 long double 值保存到 RDB 文件中。 double 可以是有效数字、NaN 或无穷大。 可以使用 RedisModule_LoadLongDouble()
加载回该值。
RedisModule_LoadLongDouble
long double RedisModule_LoadLongDouble(RedisModuleIO *io);
自版本 6.0.0
在模块数据类型的 rdb_save
方法的上下文中,加载回 RedisModule_SaveLongDouble()
保存的 long double 值。
键摘要 API(模块类型的 DEBUG DIGEST 接口)
RedisModule_DigestAddStringBuffer
void RedisModule_DigestAddStringBuffer(RedisModuleDigest *md,
const char *ele,
size_t len);
自版本 4.0.0
向摘要添加一个新元素。 此函数可以多次调用,每次调用一个元素,用于构成给定数据结构的所有元素。 函数调用必须在调用 RedisModule_DigestEndSequence
之后,最终当所有始终以给定顺序添加的元素都被添加时。 有关更多信息,请参阅 Redis 模块数据类型文档。 但是,这是一个使用 Redis 数据类型作为示例的快速示例。
要添加一系列无序元素(例如在 Redis 集的情况下),要使用的模式是
foreach element {
AddElement(element);
EndSequence();
}
因为集合是无序的,所以添加的每个元素的位置都不依赖于其他元素。 但是,如果我们的元素按对排序,例如哈希的字段值对,那么应该使用
foreach key,value {
AddElement(key);
AddElement(value);
EndSequence();
}
因为键和值始终处于上述顺序,而单个键值对可以出现在 Redis 哈希中的任何位置。
有序元素列表将使用以下方法实现
foreach element {
AddElement(element);
}
EndSequence();
RedisModule_DigestAddLongLong
void RedisModule_DigestAddLongLong(RedisModuleDigest *md, long long ll);
自版本 4.0.0
与 RedisModule_DigestAddStringBuffer()
相似,但接受一个 long long
作为输入,该输入在添加到摘要之前转换为字符串。
RedisModule_DigestEndSequence
void RedisModule_DigestEndSequence(RedisModuleDigest *md);
自版本 4.0.0
请参阅 RedisModule_DigestAddElement()
的文档。
RedisModule_LoadDataTypeFromStringEncver
void *RedisModule_LoadDataTypeFromStringEncver(const RedisModuleString *str,
const moduleType *mt,
int encver);
自版本 7.0.0
从字符串 'str' 中解码模块数据类型 'mt' 的序列化表示,在特定编码版本 'encver' 中,并返回一个新分配的值,如果解码失败则返回 NULL。
此调用基本上重新使用 'rdb_load
' 回调,模块数据类型实现它以允许模块任意地序列化/反序列化键,类似于 Redis 'DUMP' 和 'RESTORE' 命令的实现方式。
模块通常应该使用 REDISMODULE_OPTIONS_HANDLE_IO_ERRORS
标志并确保反序列化代码正确检查和处理 IO 错误(释放分配的缓冲区并返回 NULL)。
如果未完成此操作,Redis 将通过生成错误消息并终止进程来处理损坏(或只是截断)的序列化数据。
RedisModule_LoadDataTypeFromString
void *RedisModule_LoadDataTypeFromString(const RedisModuleString *str,
const moduleType *mt);
自版本 6.0.0
与 RedisModule_LoadDataTypeFromStringEncver
相似,API 的原始版本,保留以实现向后兼容性。
RedisModule_SaveDataTypeToString
RedisModuleString *RedisModule_SaveDataTypeToString(RedisModuleCtx *ctx,
void *data,
const moduleType *mt);
自版本 6.0.0
将模块数据类型 'mt' 值 'data' 编码为序列化形式,并将其作为新分配的 RedisModuleString
返回。
此调用基本上重新使用 'rdb_save
' 回调,模块数据类型实现它以允许模块任意地序列化/反序列化键,类似于 Redis 'DUMP' 和 'RESTORE' 命令的实现方式。
RedisModule_GetKeyNameFromDigest
const RedisModuleString *RedisModule_GetKeyNameFromDigest(RedisModuleDigest *dig);
自版本 7.0.0
返回当前正在处理的键的名称。
RedisModule_GetDbIdFromDigest
int RedisModule_GetDbIdFromDigest(RedisModuleDigest *dig);
自版本 7.0.0
返回当前正在处理的键的数据库 ID。
模块数据类型的 AOF API
RedisModule_EmitAOF
void RedisModule_EmitAOF(RedisModuleIO *io,
const char *cmdname,
const char *fmt,
...);
自版本 4.0.0
在 AOF 重写过程中将命令发送到 AOF。 此函数仅在模块导出的数据类型的 aof_rewrite
方法的上下文中调用。 该命令与 RedisModule_Call()
的参数传递方式完全相同,但它不返回任何内容,因为错误处理由 Redis 本身执行。
IO 上下文处理
RedisModule_GetKeyNameFromIO
const RedisModuleString *RedisModule_GetKeyNameFromIO(RedisModuleIO *io);
自版本 5.0.5
返回当前正在处理的键的名称。 无法保证键名始终可用,因此这可能会返回 NULL。
RedisModule_GetKeyNameFromModuleKey
const RedisModuleString *RedisModule_GetKeyNameFromModuleKey(RedisModuleKey *key);
自版本 6.0.0
返回一个包含 RedisModuleKey
中键名的 RedisModuleString
。
RedisModule_GetDbIdFromModuleKey
int RedisModule_GetDbIdFromModuleKey(RedisModuleKey *key);
自版本 7.0.0
返回 RedisModuleKey
中键的数据库 ID。
RedisModule_GetDbIdFromIO
int RedisModule_GetDbIdFromIO(RedisModuleIO *io);
自版本 7.0.0
返回当前正在处理的键的数据库 ID。 无法保证此信息始终可用,因此这可能会返回 -1。
日志记录
RedisModule_Log
void RedisModule_Log(RedisModuleCtx *ctx,
const char *levelstr,
const char *fmt,
...);
自版本 4.0.0
向标准 Redis 日志生成一条日志消息,格式接受类似 printf 的说明符,而级别是一个字符串,描述在发出日志时要使用的日志级别,并且必须是以下之一
- "debug" (
REDISMODULE_LOGLEVEL_DEBUG
) - "verbose" (
REDISMODULE_LOGLEVEL_VERBOSE
) - "notice" (
REDISMODULE_LOGLEVEL_NOTICE
) - "warning" (
REDISMODULE_LOGLEVEL_WARNING
)
如果指定的日志级别无效,则默认使用 verbose。 此函数能够发出的日志行的长度有一个固定限制,此限制未指定,但保证超过几行文本。
如果在调用者上下文中无法提供 ctx 参数(例如线程或回调),则它可能是 NULL,在这种情况下,将使用通用 "module" 而不是模块名称。
RedisModule_LogIOError
void RedisModule_LogIOError(RedisModuleIO *io,
const char *levelstr,
const char *fmt,
...);
自版本 4.0.0
记录来自 RDB/AOF 序列化回调的错误。
当回调返回关键错误给调用者时,应该使用此函数,因为它由于某些关键原因无法加载或保存数据。
RedisModule__Assert
void RedisModule__Assert(const char *estr, const char *file, int line);
自版本 6.0.0
类似 Redis 的断言函数。
建议使用宏 RedisModule_Assert(expression)
,而不是直接调用此函数。
断言失败将关闭服务器并生成与 Redis 本身生成的日志信息相同的日志信息。
RedisModule_LatencyAddSample
void RedisModule_LatencyAddSample(const char *event, mstime_t latency);
自版本 6.0.0
允许将事件添加到延迟监控器,以便由 LATENCY 命令观察。 如果延迟小于配置的延迟监控阈值,则会跳过此调用。
从模块阻止客户端
有关模块中阻塞命令的指南,请参阅 https://redis.ac.cn/docs/latest/develop/reference/modules/modules-blocking-ops/。
RedisModule_RegisterAuthCallback
void RedisModule_RegisterAuthCallback(RedisModuleCtx *ctx,
RedisModuleAuthCallback cb);
自版本 7.2.0
此 API 注册一个回调,除了正常的基于密码的身份验证外,还会执行该回调。 可以在不同的模块中注册多个回调。 当模块卸载时,它注册的所有身份验证回调都会被注销。 当调用 AUTH/HELLO(提供了 AUTH 字段)命令时,会尝试回调(按最近注册的顺序,从第一个开始)。 回调将使用模块上下文以及用户名和密码来调用,并且预计将执行以下操作之一:(1)身份验证 - 使用 RedisModule_AuthenticateClient
* API 并返回 REDISMODULE_AUTH_HANDLED
。 这将立即结束身份验证链作为成功并添加 OK 回复。(2)拒绝身份验证 - 返回 REDISMODULE_AUTH_HANDLED
,不进行身份验证或阻止客户端。 可选地,err
可以设置为自定义错误消息,并且 err
将由服务器自动释放。 这将立即结束身份验证链作为失败并添加 ERR 回复。(3)在身份验证时阻止客户端 - 使用 RedisModule_BlockClientOnAuth
API 并返回 REDISMODULE_AUTH_HANDLED
。 在这里,客户端将被阻止,直到使用 RedisModule_UnblockClient
API,这将触发身份验证回复回调(通过 RedisModule_BlockClientOnAuth
提供)。 在此回复回调中,模块应该进行身份验证、拒绝或跳过处理身份验证。(4)跳过处理身份验证 - 返回 REDISMODULE_AUTH_NOT_HANDLED
,不阻止客户端。 这将允许引擎尝试下一个模块身份验证回调。 如果没有回调进行身份验证或拒绝身份验证,则会尝试基于密码的身份验证,并将相应地对客户端进行身份验证或添加失败日志和回复。
注意:如果客户端在模块身份验证阻塞的中间断开连接,则 AUTH 或 HELLO 命令的该出现将不会在 INFO 命令统计信息中跟踪。
以下是如何使用非阻塞模块式身份验证的示例
int auth_cb(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *password, RedisModuleString **err) {
const char *user = RedisModule_StringPtrLen(username, NULL);
const char *pwd = RedisModule_StringPtrLen(password, NULL);
if (!strcmp(user,"foo") && !strcmp(pwd,"valid_password")) {
RedisModule_AuthenticateClientWithACLUser(ctx, "foo", 3, NULL, NULL, NULL);
return REDISMODULE_AUTH_HANDLED;
}
else if (!strcmp(user,"foo") && !strcmp(pwd,"wrong_password")) {
RedisModuleString *log = RedisModule_CreateString(ctx, "Module Auth", 11);
RedisModule_ACLAddLogEntryByUserName(ctx, username, log, REDISMODULE_ACL_LOG_AUTH);
RedisModule_FreeString(ctx, log);
const char *err_msg = "Auth denied by Misc Module.";
*err = RedisModule_CreateString(ctx, err_msg, strlen(err_msg));
return REDISMODULE_AUTH_HANDLED;
}
return REDISMODULE_AUTH_NOT_HANDLED;
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
if (RedisModule_Init(ctx,"authmodule",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)
return REDISMODULE_ERR;
RedisModule_RegisterAuthCallback(ctx, auth_cb);
return REDISMODULE_OK;
}
RedisModule_BlockClient
RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx,
RedisModuleCmdFunc reply_callback,
;
自版本 4.0.0
在阻塞命令的上下文中阻止客户端,返回一个句柄,该句柄将在稍后用于使用对 RedisModule_UnblockClient()
的调用来取消阻止客户端。 参数指定回调函数和超时时间,之后客户端将被取消阻止。
回调在以下上下文中调用
reply_callback: called after a successful RedisModule_UnblockClient()
call in order to reply to the client and unblock it.
timeout_callback: called when the timeout is reached or if `CLIENT UNBLOCK`
is invoked, in order to send an error to the client.
free_privdata: called in order to free the private data that is passed
by RedisModule_UnblockClient() call.
注意:对于每个被阻止的客户端,都应该调用 RedisModule_UnblockClient
,即使客户端被杀死、超时或断开连接。 否则会导致内存泄漏。
在某些情况下,无法使用 RedisModule_BlockClient()
- 如果客户端是 Lua 脚本。
- 如果客户端正在执行 MULTI 块。
在这些情况下,对 RedisModule_BlockClient()
的调用 **不会** 阻止客户端,而是生成一个特定的错误回复。
注册了 timeout_callback
函数的模块也可以使用 CLIENT UNBLOCK
命令取消阻止,这将触发超时回调。 如果没有注册回调函数,则被阻止的客户端将被视为不在阻塞状态,并且 CLIENT UNBLOCK
将返回零值。
测量后台时间:默认情况下,阻塞命令中花费的时间不计入总命令持续时间。 要包含此类时间,您应该使用 RedisModule_BlockedClientMeasureTimeStart()
和 RedisModule_BlockedClientMeasureTimeEnd()
一次或多次在阻塞命令后台工作中。
RedisModule_BlockClientOnAuth
RedisModuleBlockedClient *RedisModule_BlockClientOnAuth(RedisModuleCtx *ctx,
RedisModuleAuthCallback reply_callback,
;
自版本 7.2.0
在后台阻止当前客户端进行模块身份验证。 如果客户端上没有进行模块身份验证,则 API 返回 NULL。 否则,客户端将被阻止,并且返回 RedisModule_BlockedClient
,类似于 RedisModule_BlockClient
API。 注意:仅在模块身份验证回调的上下文中使用此 API。
RedisModule_BlockClientGetPrivateData
void *RedisModule_BlockClientGetPrivateData(RedisModuleBlockedClient *blocked_client);
自版本 7.2.0
获取先前在被阻止的客户端上设置的私有数据
RedisModule_BlockClientSetPrivateData
void RedisModule_BlockClientSetPrivateData(RedisModuleBlockedClient *blocked_client,
void *private_data);
自版本 7.2.0
在被阻止的客户端上设置私有数据
RedisModule_BlockClientOnKeys
RedisModuleBlockedClient *RedisModule_BlockClientOnKeys(RedisModuleCtx *ctx,
RedisModuleCmdFunc reply_callback,
;
自版本 6.0.0
此调用类似于 RedisModule_BlockClient()
,但是在这种情况下,我们不仅仅阻止客户端,还要求 Redis 在某些键变为“就绪”时自动取消阻止它,也就是说,包含更多数据。
基本上这类似于典型的 Redis 命令通常执行的操作,例如 BLPOP 或 BZPOPMAX:如果客户端不能立即得到服务,则会阻止它,稍后当键收到新数据(例如列表推送)时,客户端会被取消阻止并得到服务。
但是,在这种模块 API 的情况下,客户端何时会被取消阻止?
- 如果您对具有关联的阻塞操作的类型(例如列表、排序集、流等)的键进行阻塞,则一旦相关的键成为通常取消阻止该类型的本机阻塞操作的操作的目标,客户端可能会被取消阻止。 因此,如果我们对列表键进行阻塞,则 RPUSH 命令可能会取消阻止我们的客户端,等等。
- 如果您正在实现自己的本机数据类型,或者您想要除了“1”之外添加新的取消阻塞条件,您可以调用模块 API
RedisModule_SignalKeyAsReady()
。
无论如何,我们不能确定客户端是否应该仅因为键被标记为就绪而被取消阻止:例如,后续操作可能会更改键,或者排在这个客户端之前的客户端可能会得到服务,也可能更改键,并使其再次变为空。 因此,当客户端使用 RedisModule_BlockClientOnKeys()
被阻止时,在调用 RedisModule_UnblockClient()
之后不会调用回复回调,而是在每次键被标记为就绪时调用:如果回复回调可以服务客户端,则它将返回 REDISMODULE_OK
,并且客户端会被取消阻止,否则它将返回 REDISMODULE_ERR
,我们将在稍后重试。
回复回调可以通过调用 API RedisModule_GetBlockedClientReadyKey()
来访问被标记为已准备好的键,该 API 返回键的字符串名称,以 RedisModuleString
对象形式表示。
得益于此系统,我们可以设置复杂的阻塞场景,例如,只有当列表至少包含 5 个项目或其他更复杂的逻辑时才解除客户端的阻塞。
请注意,与 RedisModule_BlockClient()
另一个不同之处在于,这里我们在阻塞客户端时直接传递私有数据:它以后将在回复回调中可用。通常,当使用 RedisModule_BlockClient()
阻塞时,用于回复客户端的私有数据是在调用 RedisModule_UnblockClient()
时传递的,但这里 Redis 本身执行解除阻塞操作,因此我们需要预先有一些私有数据。私有数据用于存储与您正在实现的特定解除阻塞操作有关的任何信息。此类信息将使用用户提供的 free_privdata
回调释放。
但是,回复回调将能够访问命令的参数向量,因此通常不需要私有数据。
注意:在正常情况下,不应针对在键上阻塞的客户端调用 RedisModule_UnblockClient
(键要么会变为准备就绪,要么会发生超时)。如果您出于某种原因确实想要调用 RedisModule_UnblockClient,则可以这样做:客户端将被视为超时(在这种情况下,您必须实现超时回调)。
RedisModule_BlockClientOnKeysWithFlags
RedisModuleBlockedClient *RedisModule_BlockClientOnKeysWithFlags(RedisModuleCtx *ctx,
RedisModuleCmdFunc reply_callback,
;
自版本 7.2.0
与 RedisModule_BlockClientOnKeys
相同,但可以接受 REDISMODULE_BLOCK_
* 标志,可以是 REDISMODULE_BLOCK_UNBLOCK_DEFAULT
,这意味着默认行为(与调用 RedisModule_BlockClientOnKeys
相同)
标志是以下标志的位掩码:
REDISMODULE_BLOCK_UNBLOCK_DELETED
:如果任何keys
被删除,则应唤醒客户端。这对需要键存在的命令(如 XREADGROUP)非常有用。
RedisModule_SignalKeyAsReady
void RedisModule_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key);
自版本 6.0.0
此函数用于潜在地解除使用 RedisModule_BlockClientOnKeys()
在键上阻塞的客户端的阻塞。当调用此函数时,为该键阻塞的所有客户端都将调用其 reply_callback
。
RedisModule_UnblockClient
int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata);
自版本 4.0.0
解除由 RedisModule_BlockedClient
阻塞的客户端的阻塞。这将触发回复回调,以便按顺序调用这些回调以回复客户端。'privdata' 参数将在回复回调中可用,因此此函数的调用者可以传递任何在实际回复客户端时所需的值。
'privdata' 的常用用途是线程,该线程计算需要传递给客户端的内容,包括但不限于一些需要缓慢计算的回复或通过网络获得的一些回复。
注意 1:此函数可以从模块生成的线程中调用。
注意 2:当我们解除使用 API RedisModule_BlockClientOnKeys()
在键上阻塞的客户端的阻塞时,这里的 privdata 参数不会被使用。使用此 API 解除在键上阻塞的客户端的阻塞仍然需要客户端获得一些回复,因此该函数将使用“超时”处理程序来执行此操作(在 RedisModule_BlockClientOnKeys()
中提供的 privdata 可通过 RedisModule_GetBlockedClientPrivateData
从超时回调访问)。
RedisModule_AbortBlock
int RedisModule_AbortBlock(RedisModuleBlockedClient *bc);
自版本 4.0.0
中止阻塞的客户端阻塞操作:客户端将被解除阻塞,不会触发任何回调。
RedisModule_SetDisconnectCallback
void RedisModule_SetDisconnectCallback(RedisModuleBlockedClient *bc,
RedisModuleDisconnectFunc callback);
自版本 5.0.0
设置一个回调,如果阻塞的客户端在模块有机会调用 RedisModule_UnblockClient()
之前断开连接,则会调用该回调。
通常,您需要在那里做的事情是清理您的模块状态,以便您可以安全地调用 RedisModule_UnblockClient()
,否则如果超时时间很长,客户端将永远保持阻塞状态。
注意
-
在此处调用 Reply* 系列函数是不安全的,这也是没有用的,因为客户端已消失。
-
如果客户端由于超时而断开连接,则不会调用此回调。在这种情况下,客户端会自动解除阻塞,并会调用超时回调。
RedisModule_IsBlockedReplyRequest
int RedisModule_IsBlockedReplyRequest(RedisModuleCtx *ctx);
自版本 4.0.0
如果模块命令被调用以填充阻塞客户端的回复,则返回非零值。
RedisModule_IsBlockedTimeoutRequest
int RedisModule_IsBlockedTimeoutRequest(RedisModuleCtx *ctx);
自版本 4.0.0
如果模块命令被调用以填充超时的阻塞客户端的回复,则返回非零值。
RedisModule_GetBlockedClientPrivateData
void *RedisModule_GetBlockedClientPrivateData(RedisModuleCtx *ctx);
自版本 4.0.0
获取由 RedisModule_UnblockClient()
设置的私有数据。
RedisModule_GetBlockedClientReadyKey
RedisModuleString *RedisModule_GetBlockedClientReadyKey(RedisModuleCtx *ctx);
自版本 6.0.0
获取在回复回调被调用时处于由 RedisModule_BlockClientOnKeys()
阻塞的客户端上下文中已准备好的键。
RedisModule_GetBlockedClientHandle
RedisModuleBlockedClient *RedisModule_GetBlockedClientHandle(RedisModuleCtx *ctx);
自版本 5.0.0
获取与给定上下文关联的阻塞客户端。这在阻塞客户端的回复和超时回调中很有用,因为有时模块会围绕阻塞客户端句柄引用,并希望清理它。
RedisModule_BlockedClientDisconnected
int RedisModule_BlockedClientDisconnected(RedisModuleCtx *ctx);
自版本 5.0.0
如果在调用阻塞客户端的 free 回调时,客户端被解除阻塞的原因是它在被阻塞时断开连接,则返回 true。
线程安全上下文
RedisModule_GetThreadSafeContext
RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc);
自版本 4.0.0
返回一个上下文,该上下文可以在线程内部使用,以便使用某些模块 API 进行 Redis 上下文调用。如果 'bc' 不为 NULL,则模块将绑定到阻塞的客户端,并且可以使用 RedisModule_Reply*
函数系列来累积一个回复,以便在客户端被解除阻塞时提供。否则,线程安全上下文将与特定客户端分离。
要调用非回复 API,线程安全上下文必须使用以下方法准备:
RedisModule_ThreadSafeContextLock(ctx);
... make your call here ...
RedisModule_ThreadSafeContextUnlock(ctx);
如果在创建上下文时使用了阻塞客户端,则在使用 RedisModule_Reply*
函数时无需执行此操作,否则绝不应执行任何 RedisModule_Reply
* 调用。
注意:如果您正在创建分离的线程安全上下文(bc 为 NULL),请考虑使用 RedisModule_GetDetachedThreadSafeContext
,它还会保留模块 ID,因此对于日志记录更有用。
RedisModule_GetDetachedThreadSafeContext
RedisModuleCtx *RedisModule_GetDetachedThreadSafeContext(RedisModuleCtx *ctx);
自版本 6.0.9
返回一个分离的线程安全上下文,该上下文不与任何特定的阻塞客户端关联,但与模块的上下文关联。
这对于希望在长期内保持全局上下文的模块很有用,例如用于日志记录。
RedisModule_FreeThreadSafeContext
void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx);
自版本 4.0.0
释放线程安全上下文。
RedisModule_ThreadSafeContextLock
void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx);
自版本 4.0.0
在执行线程安全 API 调用之前获取服务器锁。如果线程安全上下文连接了阻塞客户端,则对于 RedisModule_Reply*
调用,无需执行此操作。
RedisModule_ThreadSafeContextTryLock
int RedisModule_ThreadSafeContextTryLock(RedisModuleCtx *ctx);
自版本 6.0.8
类似于 RedisModule_ThreadSafeContextLock
,但如果服务器锁已经被获取,则此函数不会阻塞。
如果成功(获取锁),则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
,并相应地设置 errno。
RedisModule_ThreadSafeContextUnlock
void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx);
自版本 4.0.0
在执行线程安全 API 调用后释放服务器锁。
模块键空间通知 API
RedisModule_SubscribeToKeyspaceEvents
int RedisModule_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx,
int types,
RedisModuleNotificationFunc callback);
自版本 4.0.9
订阅键空间通知。这是键空间通知 API 的低级版本。模块可以注册回调以在发生键空间事件时收到通知。
通知事件按其类型(字符串事件、集合事件等)进行过滤,订阅者回调仅接收与特定事件类型掩码匹配的事件。
当使用 RedisModule_SubscribeToKeyspaceEvents
订阅通知时,模块必须提供一个事件类型掩码,表示订阅者感兴趣的事件。这可以是以下任何标志的 ORed 掩码:
REDISMODULE_NOTIFY_GENERIC
:通用命令,如 DEL、EXPIRE、RENAMEREDISMODULE_NOTIFY_STRING
:字符串事件REDISMODULE_NOTIFY_LIST
:列表事件REDISMODULE_NOTIFY_SET
:集合事件REDISMODULE_NOTIFY_HASH
:哈希事件REDISMODULE_NOTIFY_ZSET
:排序集合事件REDISMODULE_NOTIFY_EXPIRED
:过期事件REDISMODULE_NOTIFY_EVICTED
:驱逐事件REDISMODULE_NOTIFY_STREAM
:流事件REDISMODULE_NOTIFY_MODULE
:模块类型事件REDISMODULE_NOTIFY_KEYMISS
:键丢失事件注意,键丢失事件是唯一一种从读取命令内部触发的事件类型。在此通知内使用写入命令执行 RedisModule_Call 是错误的,并且不鼓励这样做。这会导致触发事件的读取命令被复制到 AOF/副本。REDISMODULE_NOTIFY_ALL
:所有事件(不包括REDISMODULE_NOTIFY_KEYMISS
)REDISMODULE_NOTIFY_LOADED
:仅针对模块提供的特殊通知,指示键是从持久性存储中加载的。注意,当此事件触发时,给定的键无法保留,请改用 RedisModule_CreateStringFromString。
我们不区分键事件和键空间事件,模块负责根据键过滤所采取的操作。
订阅者签名是:
int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type,
const char *event,
RedisModuleString *key);
type
是事件类型位,必须与注册时提供的掩码匹配。事件字符串是正在执行的实际命令,key 是相关的 Redis 键。
通知回调使用 Redis 上下文执行,该上下文不能用于向客户端发送任何内容,并且其所选数据库编号为事件发生的数据库编号。
请注意,对于模块通知正常工作,无需在 redis.conf 中启用通知。
警告:通知回调以同步方式执行,因此通知回调必须很快,否则会降低 Redis 的速度。如果您需要执行长时间操作,请使用线程来卸载它们。
此外,通知以同步方式执行的事实意味着通知代码将在 Redis 逻辑(命令逻辑、驱逐、过期)的中间执行。在逻辑运行时更改键空间是危险的,并且不建议这样做。为了使用写入操作对键空间事件做出反应,请参考 RedisModule_AddPostNotificationJob
。
有关更多信息,请参见 https://redis.ac.cn/topics/notifications。
RedisModule_AddPostNotificationJob
int RedisModule_AddPostNotificationJob(RedisModuleCtx *ctx,
RedisModulePostNotificationJobFunc callback,
void *privdata,
void (*free_privdata)(void*));
自版本 7.2.0
在键空间通知回调内部运行时,执行任何写入操作都是危险的,并且强烈不建议这样做(参见 RedisModule_SubscribeToKeyspaceEvents
)。为了在这种情况下仍然执行写入操作,Redis 提供了 RedisModule_AddPostNotificationJob
API。该 API 允许注册一个作业回调,Redis 将在满足以下条件时调用该回调:
- 执行任何写入操作都是安全的。
- 该作业将与键空间通知一起原子地调用。
注意,一个作业可能会触发键空间通知,从而触发更多作业。这会引发进入无限循环的担忧,我们认为无限循环是需要在模块中修复的逻辑错误,试图通过停止执行来防止无限循环会导致违反功能正确性,因此 Redis 不会尝试保护模块免受无限循环。
'free_pd
' 可以为 NULL,在这种情况下不会被使用。
如果成功,则返回 REDISMODULE_OK
,如果在从磁盘(AOF 或 RDB)加载数据时调用或如果实例是只读副本,则返回 REDISMODULE_ERR
。
RedisModule_GetNotifyKeyspaceEvents
int RedisModule_GetNotifyKeyspaceEvents(void);
自版本 6.0.0
获取已配置的 notify-keyspace-events 位图(可在 RedisModuleNotificationFunc
中用于额外的过滤)。
RedisModule_NotifyKeyspaceEvent
int RedisModule_NotifyKeyspaceEvent(RedisModuleCtx *ctx,
int type,
const char *event,
RedisModuleString *key);
自版本 6.0.0
将 notifyKeyspaceEvent 公开给模块。
模块集群 API
RedisModule_RegisterClusterMessageReceiver
void RedisModule_RegisterClusterMessageReceiver(RedisModuleCtx *ctx,
uint8_t type,
RedisModuleClusterMessageReceiver callback);
自版本 5.0.0
注册类型为 'type' 的集群消息的回调接收器。如果之前已经注册了回调,则这将使用提供的回调函数替换回调函数,否则如果回调被设置为 NULL 并且已经存在此函数的回调,则取消注册回调(因此此 API 调用也用于删除接收器)。
RedisModule_SendClusterMessage
int RedisModule_SendClusterMessage(RedisModuleCtx *ctx,
const char *target_id,
uint8_t type,
const char *msg,
uint32_t len);
自版本 5.0.0
如果target
为NULL,则向集群中的所有节点发送消息,否则向指定的target
发送消息,target
是一个REDISMODULE_NODE_ID_LEN
字节的节点ID,由接收器回调函数或节点迭代函数返回。
如果消息成功发送,则函数返回REDISMODULE_OK
,否则如果节点未连接或该节点ID未映射到任何已知集群节点,则返回REDISMODULE_ERR
。
RedisModule_GetClusterNodesList
char **RedisModule_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes);
自版本 5.0.0
返回一个字符串指针数组,每个字符串指针指向一个长度为REDISMODULE_NODE_ID_LEN
字节的集群节点ID(不包含任何空字符)。返回的节点ID数量存储在*numnodes
中。但是,如果此函数由未在启用Redis集群的Redis实例上运行的模块调用,则返回NULL。
返回的ID可以与RedisModule_GetClusterNodeInfo()
一起使用,以便获取有关单个节点的更多信息。
使用函数RedisModule_FreeClusterNodesList()
释放此函数返回的数组。
示例
size_t count, j;
char **ids = RedisModule_GetClusterNodesList(ctx,&count);
for (j = 0; j < count; j++) {
RedisModule_Log(ctx,"notice","Node %.*s",
REDISMODULE_NODE_ID_LEN,ids[j]);
}
RedisModule_FreeClusterNodesList(ids);
RedisModule_FreeClusterNodesList
void RedisModule_FreeClusterNodesList(char **ids);
自版本 5.0.0
释放使用RedisModule_GetClusterNodesList
获得的节点列表。
RedisModule_GetMyClusterID
const char *RedisModule_GetMyClusterID(void);
自版本 5.0.0
返回此节点ID(REDISMODULE_CLUSTER_ID_LEN
字节),如果集群已禁用则返回NULL。
RedisModule_GetClusterSize
size_t RedisModule_GetClusterSize(void);
自版本 5.0.0
返回集群中的节点数量,无论其状态如何(握手、无地址等),因此实际的活动节点数量可能更小,但不会大于此数量。如果实例不在集群模式下,则返回零。
RedisModule_GetClusterNodeInfo
int RedisModule_GetClusterNodeInfo(RedisModuleCtx *ctx,
const char *id,
char *ip,
char *master_id,
int *port,
int *flags);
自版本 5.0.0
填充指定ID为'id'的节点的指定信息,然后返回REDISMODULE_OK
。否则,如果节点ID的格式无效或节点ID从本地节点的角度来看不存在,则返回REDISMODULE_ERR
。
如果我们不需要填充回某些信息,则参数ip
、master_id
、port
和flags
可以为NULL。如果指定了ip
和master_id
(仅在实例为从节点时填充),则它们指向至少包含REDISMODULE_NODE_ID_LEN
字节的缓冲区。写入回ip
和master_id
的字符串没有空终止符。
报告的标志列表如下:
REDISMODULE_NODE_MYSELF
: 此节点REDISMODULE_NODE_MASTER
: 节点为主节点REDISMODULE_NODE_SLAVE
: 节点为从节点REDISMODULE_NODE_PFAIL
: 我们认为节点正在故障REDISMODULE_NODE_FAIL
: 集群同意节点正在故障REDISMODULE_NODE_NOFAILOVER
: 从节点配置为从不故障转移
RedisModule_SetClusterFlags
void RedisModule_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags);
自版本 5.0.0
设置Redis集群标志,以便更改Redis集群的正常行为,特别是为了禁用某些功能。这对于使用集群API创建不同分布式系统的模块很有用,但仍然希望使用Redis集群消息总线。可以设置的标志
CLUSTER_MODULE_FLAG_NO_FAILOVER
CLUSTER_MODULE_FLAG_NO_REDIRECTION
具有以下效果
-
NO_FAILOVER
: 阻止Redis集群从节点在主节点失效后进行故障转移。同时禁用副本迁移功能。 -
NO_REDIRECTION
: 每个节点都将接受任何键,而不会尝试根据Redis集群算法执行分区。槽位信息仍将传播到整个集群,但没有效果。
RedisModule_ClusterKeySlot
unsigned int RedisModule_ClusterKeySlot(RedisModuleString *key);
自版本 7.4.0
返回键的集群槽位,类似于CLUSTER KEYSLOT
命令。即使启用集群模式,此函数也能正常工作。
RedisModule_ClusterCanonicalKeyNameInSlot
const char *RedisModule_ClusterCanonicalKeyNameInSlot(unsigned int slot);
自版本 7.4.0
返回一个短字符串,可以作为键或键中的哈希标签使用,这样键就会映射到给定的集群槽位。如果槽位不是有效槽位,则返回NULL。
模块计时器 API
模块计时器是一个高精度“绿色计时器”抽象,每个模块都可以注册数百万个计时器,而不会出现问题,即使实际的事件循环只有一个计时器,用于唤醒模块计时器子系统以处理下一个事件。
所有计时器都存储在一个基数树中,按过期时间排序,当主Redis事件循环计时器回调函数被调用时,我们尝试按顺序处理所有已过期的计时器。然后,我们重新进入事件循环,注册一个在下一个要处理的模块计时器过期时过期的计时器。
每当活动计时器列表降至零时,我们都会注销主事件循环计时器,这样在不使用此功能时就不会产生开销。
RedisModule_CreateTimer
RedisModuleTimerID RedisModule_CreateTimer(RedisModuleCtx *ctx,
mstime_t period,
RedisModuleTimerProc callback,
void *data);
自版本 5.0.0
创建一个新的计时器,该计时器将在period
毫秒后触发,并将使用data
作为参数调用指定的函数。返回的计时器ID可用于从计时器获取信息或在计时器触发之前停止计时器。请注意,对于重复计时器的常见用例(在RedisModuleTimerProc
回调函数内部重新注册计时器),调用此API的时间很重要:如果在'回调函数'的开头调用它,则表示事件将每隔'period'时间触发一次。如果在'回调函数'的末尾调用它,则表示事件之间将有'period'毫秒的间隔。(如果执行'回调函数'所需的时间可以忽略不计,则上面两个语句的意思相同)
RedisModule_StopTimer
int RedisModule_StopTimer(RedisModuleCtx *ctx,
RedisModuleTimerID id,
void **data);
自版本 5.0.0
停止一个计时器,如果找到计时器,它属于调用模块并且已停止,则返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
。如果data指针不为空,则将其设置为创建计时器时data参数的值。
RedisModule_GetTimerInfo
int RedisModule_GetTimerInfo(RedisModuleCtx *ctx,
RedisModuleTimerID id,
uint64_t *remaining,
void **data);
自版本 5.0.0
获取有关计时器的信息:其剩余触发时间(以毫秒为单位)以及与计时器关联的私有数据指针。如果指定的计时器不存在或属于不同的模块,则不返回任何信息,函数返回REDISMODULE_ERR
,否则返回REDISMODULE_OK
。如果调用者不需要某些信息,则参数remaining或data可以为NULL。
模块事件循环 API
RedisModule_EventLoopAdd
int RedisModule_EventLoopAdd(int fd,
int mask,
RedisModuleEventLoopFunc func,
void *user_data);
自版本 7.0.0
将管道/套接字事件添加到事件循环中。
-
mask
必须是以下值之一REDISMODULE_EVENTLOOP_READABLE
REDISMODULE_EVENTLOOP_WRITABLE
REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE
成功时返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
,并将errno设置为以下值
- ERANGE:
fd
为负数或大于maxclients
Redis配置。 - EINVAL:
callback
为NULL或mask
值无效。
errno
在发生内部错误的情况下可能采用其他值。
示例
void onReadable(int fd, void *user_data, int mask) {
char buf[32];
int bytes = read(fd,buf,sizeof(buf));
printf("Read %d bytes \n", bytes);
}
RedisModule_EventLoopAdd(fd, REDISMODULE_EVENTLOOP_READABLE, onReadable, NULL);
RedisModule_EventLoopDel
int RedisModule_EventLoopDel(int fd, int mask);
自版本 7.0.0
从事件循环中删除管道/套接字事件。
-
mask
必须是以下值之一REDISMODULE_EVENTLOOP_READABLE
REDISMODULE_EVENTLOOP_WRITABLE
REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE
成功时返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
,并将errno设置为以下值
- ERANGE:
fd
为负数或大于maxclients
Redis配置。 - EINVAL:
mask
值无效。
RedisModule_EventLoopAddOneShot
int RedisModule_EventLoopAddOneShot(RedisModuleEventLoopOneShotFunc func,
void *user_data);
自版本 7.0.0
此函数可以从其他线程调用,以在Redis主线程上触发回调。成功时返回REDISMODULE_OK
。如果func
为NULL,则返回REDISMODULE_ERR
,并将errno设置为EINVAL。
模块 ACL API
在Redis中的身份验证和授权中实现一个钩子。
RedisModule_CreateModuleUser
RedisModuleUser *RedisModule_CreateModuleUser(const char *name);
自版本 6.0.0
创建一个Redis ACL用户,模块可以使用该用户来验证客户端。在获取用户后,模块应该使用RedisModule_SetUserACL()
函数设置该用户的权限。配置完成后,可以使用该用户来验证连接,使用指定的ACL规则,使用RedisModule_AuthClientWithUser()
函数。
请注意
- 这里创建的用户不会被ACL命令列出。
- 这里创建的用户不会检查名称是否重复,因此调用此函数的模块有责任确保不会创建名称相同的用户。
- 创建的用户可以用来验证多个Redis连接。
调用者可以稍后使用函数RedisModule_FreeModuleUser()
释放用户。当调用此函数时,如果仍然有使用此用户进行身份验证的客户端,则这些客户端将断开连接。释放用户的函数仅应在调用者确实要使用户失效以定义具有不同功能的新用户时使用。
RedisModule_FreeModuleUser
int RedisModule_FreeModuleUser(RedisModuleUser *user);
自版本 6.0.0
释放给定用户并断开所有已使用该用户进行身份验证的客户端的连接。有关详细用法,请参见RedisModule_CreateModuleUser
。
RedisModule_SetModuleUserACL
int RedisModule_SetModuleUserACL(RedisModuleUser *user, const char* acl);
自版本 6.0.0
设置通过Redis模块接口创建的用户权限。语法与ACL SETUSER相同,因此请参阅acl.c中的文档以获取更多信息。有关详细用法,请参见RedisModule_CreateModuleUser
。
成功时返回REDISMODULE_OK
,失败时返回REDISMODULE_ERR
,并将设置一个描述操作失败原因的errno。
RedisModule_SetModuleUserACLString
int RedisModule_SetModuleUserACLString(RedisModuleCtx *ctx,
RedisModuleUser *user,
const char *acl,
RedisModuleString **error);
自版本 7.0.6
使用完整的ACL字符串设置用户的权限,例如在Redis ACL SETUSER命令行API中使用的那样。这与RedisModule_SetModuleUserACL
不同,后者一次只接受单个ACL操作。
成功时返回REDISMODULE_OK
,如果提供的RedisModuleString
有误,则返回REDISMODULE_ERR
,并返回一个描述错误的字符串。
RedisModule_GetModuleUserACLString
RedisModuleString *RedisModule_GetModuleUserACLString(RedisModuleUser *user);
自版本 7.0.6
获取给定用户的ACL字符串。返回一个RedisModuleString
。
RedisModule_GetCurrentUserName
RedisModuleString *RedisModule_GetCurrentUserName(RedisModuleCtx *ctx);
自版本 7.0.0
检索当前上下文后面的客户端连接的用户名。用户名可以稍后用于获取RedisModuleUser
。有关更多信息,请参见RedisModule_GetModuleUserFromUserName
。
返回的字符串必须使用 RedisModule_FreeString()
释放,或者通过启用自动内存管理释放。
RedisModule_GetModuleUserFromUserName
RedisModuleUser *RedisModule_GetModuleUserFromUserName(RedisModuleString *name);
自版本 7.0.0
可以使用RedisModuleUser
来检查命令、键或频道是否可以根据与该用户关联的ACL规则执行或访问。当模块想要对一般ACL用户(不是通过RedisModule_CreateModuleUser
创建的)执行ACL检查时,它可以根据使用RedisModule_GetCurrentUserName
检索的用户名从这个API获取RedisModuleUser
。
由于一般ACL用户可以随时删除,因此此RedisModuleUser
仅应在调用此函数的上下文中使用。为了在该上下文之外执行ACL检查,模块可以存储用户名,并在任何其他上下文中调用此API。
如果用户已禁用或用户不存在,则返回NULL。调用者应稍后使用函数RedisModule_FreeModuleUser()
释放用户。
RedisModule_ACLCheckCommandPermissions
int RedisModule_ACLCheckCommandPermissions(RedisModuleUser *user,
RedisModuleString **argv,
int argc);
自版本 7.0.0
检查用户是否可以根据与其关联的ACL执行该命令。
成功时返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
,并将errno设置为以下值
- ENOENT: 指定的命令不存在。
- EACCES: 根据 ACL 规则,无法执行命令。
RedisModule_ACLCheckKeyPermissions
int RedisModule_ACLCheckKeyPermissions(RedisModuleUser *user,
RedisModuleString *key,
int flags);
自版本 7.0.0
检查用户是否可以根据附加到用户和表示键访问的标志的ACL访问键。标志与用于逻辑运算的键规格中使用的标志相同。这些标志在RedisModule_SetCommandInfo
中作为REDISMODULE_CMD_KEY_ACCESS
、REDISMODULE_CMD_KEY_UPDATE
、REDISMODULE_CMD_KEY_INSERT
和REDISMODULE_CMD_KEY_DELETE
标志进行了说明。
如果未提供任何标志,则用户仍然需要对键具有某些访问权限才能使该命令成功返回。
如果用户能够访问该键,则返回REDISMODULE_OK
,否则返回REDISMODULE_ERR
,并将errno设置为以下值之一
- EINVAL: 提供的标志无效。
- EACCESS: 用户无权访问该键。
RedisModule_ACLCheckChannelPermissions
int RedisModule_ACLCheckChannelPermissions(RedisModuleUser *user,
RedisModuleString *ch,
int flags);
自版本 7.0.0
根据给定的访问标志检查用户是否可以访问发布订阅频道。有关可传递的标志的更多信息,请参见 RedisModule_ChannelAtPosWithFlags
。
如果用户可以访问发布订阅频道,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
并且 errno 设置为以下值之一
- EINVAL: 提供的标志无效。
- EACCESS: 用户无权访问发布订阅频道。
RedisModule_ACLAddLogEntry
int RedisModule_ACLAddLogEntry(RedisModuleCtx *ctx,
RedisModuleUser *user,
RedisModuleString *object,
RedisModuleACLLogEntryReason reason);
自版本 7.0.0
在 ACL 日志中添加一个新条目。成功时返回 REDISMODULE_OK
,错误时返回 REDISMODULE_ERR
。
有关 ACL 日志的更多信息,请参考 https://redis.ac.cn/commands/acl-log
RedisModule_ACLAddLogEntryByUserName
int RedisModule_ACLAddLogEntryByUserName(RedisModuleCtx *ctx,
RedisModuleString *username,
RedisModuleString *object,
RedisModuleACLLogEntryReason reason);
自版本 7.2.0
在 ACL 日志中添加一个新条目,并使用提供的 username
RedisModuleString
。成功时返回 REDISMODULE_OK
,错误时返回 REDISMODULE_ERR
。
有关 ACL 日志的更多信息,请参考 https://redis.ac.cn/commands/acl-log
RedisModule_AuthenticateClientWithUser
int RedisModule_AuthenticateClientWithUser(RedisModuleCtx *ctx,
RedisModuleUser *module_user,
RedisModuleUserChangedFunc callback,
void *privdata,
uint64_t *client_id);
自版本 6.0.0
使用提供的 Redis ACL 用户对当前上下文的用户进行身份验证。如果用户被禁用,则返回 REDISMODULE_ERR
。
有关回调、client_id
和身份验证的一般用法的详细信息,请参见 authenticateClientWithUser。
RedisModule_AuthenticateClientWithACLUser
int RedisModule_AuthenticateClientWithACLUser(RedisModuleCtx *ctx,
const char *name,
size_t len,
RedisModuleUserChangedFunc callback,
void *privdata,
uint64_t *client_id);
自版本 6.0.0
使用提供的 Redis ACL 用户对当前上下文的用户进行身份验证。如果用户被禁用或用户不存在,则返回 REDISMODULE_ERR
。
有关回调、client_id
和身份验证的一般用法的详细信息,请参见 authenticateClientWithUser。
RedisModule_DeauthenticateAndCloseClient
int RedisModule_DeauthenticateAndCloseClient(RedisModuleCtx *ctx,
uint64_t client_id);
自版本 6.0.0
取消身份验证并关闭客户端。客户端资源不会立即释放,而是在后台作业中清理。这是取消身份验证客户端的推荐方法,因为大多数客户端无法处理用户取消身份验证。如果客户端不存在,则返回 REDISMODULE_ERR
,如果操作成功,则返回 REDISMODULE_OK
。
客户端 ID 来自 RedisModule_AuthenticateClientWithUser
和 RedisModule_AuthenticateClientWithACLUser
API,但可以通过 CLIENT API 或服务器事件获取。
此函数不是线程安全的,必须在命令或线程安全上下文的上下文中执行。
RedisModule_RedactClientCommandArgument
int RedisModule_RedactClientCommandArgument(RedisModuleCtx *ctx, int pos);
自版本 7.0.0
屏蔽在给定位置指定的客户端命令参数。屏蔽的论据在面向用户的命令(如 SLOWLOG 或 MONITOR)中被模糊处理,并且从不写入服务器日志。此命令可以对同一位置调用多次。
请注意,命令名称(位置 0)不能被屏蔽。
如果参数被屏蔽,则返回 REDISMODULE_OK
,如果传递了无效参数或位置超出客户端参数范围,则返回 REDISMODULE_ERR
。
RedisModule_GetClientCertificate
RedisModuleString *RedisModule_GetClientCertificate(RedisModuleCtx *ctx,
uint64_t client_id);
自版本 6.0.9
返回客户端用于对该连接进行身份验证的 X.509 客户端证书。
返回值是一个分配的 RedisModuleString
,它是以 PEM(Base64)格式编码的 X.509 证书。它应该由调用方释放(或自动释放)。
在以下情况下返回 NULL 值
- 连接 ID 不存在
- 连接不是 TLS 连接
- 连接是 TLS 连接,但没有使用客户端证书
模块字典 API
实现一个排序字典(实际上由基数树支持),具有通常的 get / set / del / num-items API,以及一个能够来回移动的迭代器。
RedisModule_CreateDict
RedisModuleDict *RedisModule_CreateDict(RedisModuleCtx *ctx);
自版本 5.0.0
创建一个新字典。'ctx' 指针可以是当前模块上下文或 NULL,具体取决于您的需求。请遵循以下规则
- 如果您打算保留对该字典的引用,该引用将在创建该字典的模块回调的时间内持续存在,请使用 NULL 上下文。
- 如果您在创建字典时没有上下文可用,请使用 NULL 上下文(当然...)。
- 但是,如果您希望字典的生存时间仅限于回调范围,则将当前回调上下文用作 'ctx' 参数。在这种情况下,如果已启用,您将享受自动内存管理,该管理将回收字典内存,以及由 Next / Prev 字典迭代器调用返回的字符串。
RedisModule_FreeDict
void RedisModule_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d);
自版本 5.0.0
释放使用 RedisModule_CreateDict()
创建的字典。您需要仅当字典是使用上下文而不是传递 NULL 创建时才传递上下文指针 'ctx'。
RedisModule_DictSize
uint64_t RedisModule_DictSize(RedisModuleDict *d);
自版本 5.0.0
返回字典的大小(键的数量)。
RedisModule_DictSetC
int RedisModule_DictSetC(RedisModuleDict *d,
void *key,
size_t keylen,
void *ptr);
自版本 5.0.0
将指定的键存储到字典中,将其值设置为指针 'ptr'。如果键成功添加(因为它不存在),则返回 REDISMODULE_OK
。否则,如果键已存在,则函数返回 REDISMODULE_ERR
。
RedisModule_DictReplaceC
int RedisModule_DictReplaceC(RedisModuleDict *d,
void *key,
size_t keylen,
void *ptr);
自版本 5.0.0
与 RedisModule_DictSetC()
相似,但如果键已存在,则将用新值替换键。
RedisModule_DictSet
int RedisModule_DictSet(RedisModuleDict *d, RedisModuleString *key, void *ptr);
自版本 5.0.0
与 RedisModule_DictSetC()
相似,但将键作为 RedisModuleString
传递。
RedisModule_DictReplace
int RedisModule_DictReplace(RedisModuleDict *d,
RedisModuleString *key,
void *ptr);
自版本 5.0.0
与 RedisModule_DictReplaceC()
相似,但将键作为 RedisModuleString
传递。
RedisModule_DictGetC
void *RedisModule_DictGetC(RedisModuleDict *d,
void *key,
size_t keylen,
int *nokey);
自版本 5.0.0
返回存储在指定键处的的值。如果键不存在,或者您实际上在键处存储了 NULL,则该函数返回 NULL。因此,可以选择将 'nokey' 指针设置为 NULL,如果键不存在,则将其设置为 1,如果键存在,则将其设置为 0。
RedisModule_DictGet
void *RedisModule_DictGet(RedisModuleDict *d,
RedisModuleString *key,
int *nokey);
自版本 5.0.0
与 RedisModule_DictGetC()
相似,但将键作为 RedisModuleString
传递。
RedisModule_DictDelC
int RedisModule_DictDelC(RedisModuleDict *d,
void *key,
size_t keylen,
void *oldval);
自版本 5.0.0
从字典中删除指定的键,如果键被找到并删除,则返回 REDISMODULE_OK
,如果字典中不存在该键,则返回 REDISMODULE_ERR
。当操作成功时,如果 'oldval' 不为 NULL,则 '*oldval' 设置为删除前存储在该键处的值。使用此功能,可以获取指向该值的指针(例如为了释放它),而无需在删除该键之前调用 RedisModule_DictGet()
。
RedisModule_DictDel
int RedisModule_DictDel(RedisModuleDict *d,
RedisModuleString *key,
void *oldval);
自版本 5.0.0
与 RedisModule_DictDelC()
相似,但将键作为 RedisModuleString
传递。
RedisModule_DictIteratorStartC
RedisModuleDictIter *RedisModule_DictIteratorStartC(RedisModuleDict *d,
const char *op,
void *key,
size_t keylen);
自版本 5.0.0
返回一个迭代器,设置它以从指定的键开始迭代,方法是应用运算符 'op',它只是一个字符串,指定在搜索第一个元素时要使用的比较运算符。可用的运算符是
^
– 搜索第一个(词法上更小)键。$
– 搜索最后一个(词法上更大)键。>
– 搜索大于指定键的第一个元素。>=
– 搜索大于或等于指定键的第一个元素。<
– 搜索小于指定键的第一个元素。<=
– 搜索小于或等于指定键的第一个元素。==
– 搜索与指定键完全匹配的第一个元素。
请注意,对于 ^
和 $
,传递的键不会被使用,用户可以传递长度为 0 的 NULL。
如果无法根据传递的键和运算符搜索要开始迭代的元素,则 RedisModule_DictNext()
/ Prev() 只会在第一次调用时返回 REDISMODULE_ERR
,否则它们将生成元素。
RedisModule_DictIteratorStart
RedisModuleDictIter *RedisModule_DictIteratorStart(RedisModuleDict *d,
const char *op,
RedisModuleString *key);
自版本 5.0.0
与 RedisModule_DictIteratorStartC
完全相同,但键作为 RedisModuleString
传递。
RedisModule_DictIteratorStop
void RedisModule_DictIteratorStop(RedisModuleDictIter *di);
自版本 5.0.0
释放使用 RedisModule_DictIteratorStart()
创建的迭代器。此调用是强制性的,否则模块中会引入内存泄漏。
RedisModule_DictIteratorReseekC
int RedisModule_DictIteratorReseekC(RedisModuleDictIter *di,
const char *op,
void *key,
size_t keylen);
自版本 5.0.0
使用此 API 调用可以更改迭代器在使用 RedisModule_DictIteratorStart()
创建后当前选定的元素。根据运算符和键的结果与函数 RedisModule_DictIteratorStart()
完全相同,但是在这种情况下,返回值仅在找到搜索的元素时为 REDISMODULE_OK
,如果无法搜索指定的元素,则返回 REDISMODULE_ERR
。您可以根据需要多次重新搜索迭代器。
RedisModule_DictIteratorReseek
int RedisModule_DictIteratorReseek(RedisModuleDictIter *di,
const char *op,
RedisModuleString *key);
自版本 5.0.0
与 RedisModule_DictIteratorReseekC()
相似,但将键作为 RedisModuleString
传递。
RedisModule_DictNextC
void *RedisModule_DictNextC(RedisModuleDictIter *di,
size_t *keylen,
void **dataptr);
自版本 5.0.0
返回字典迭代器 di
的当前项目,并逐步进入下一个元素。如果迭代器已经产生了最后一个元素,并且没有其他元素要返回,则返回 NULL,否则将提供一个表示键的字符串指针,并且 *keylen
长度通过引用设置(如果 keylen 不为 NULL)。如果 *dataptr
不为 NULL,则将其设置为作为辅助数据存储在返回键处的指针的值(如 RedisModule_DictSet
API 所设置)。
使用示例
... create the iterator here ...
char *key;
void *data;
while((key = RedisModule_DictNextC(iter,&keylen,&data)) != NULL) {
printf("%.*s %p\n", (int)keylen, key, data);
}
返回的指针的类型为 void,因为有时将其转换为 char*
有意义,有时将其转换为无符号 char*
有意义,具体取决于它是否包含二进制数据,因此使用此 API 更方便。
返回指针的有效性持续到下一次调用 next/prev 迭代器步骤为止。此外,一旦释放迭代器,该指针就无效。
RedisModule_DictPrevC
void *RedisModule_DictPrevC(RedisModuleDictIter *di,
size_t *keylen,
void **dataptr);
自版本 5.0.0
此函数与 RedisModule_DictNext()
完全相同,但它在返回迭代器中当前选定的元素之后,选择上一个元素(词法上更小)而不是下一个元素。
RedisModule_DictNext
RedisModuleString *RedisModule_DictNext(RedisModuleCtx *ctx,
RedisModuleDictIter *di,
void **dataptr);
自版本 5.0.0
与 RedisModuleNextC()
相似,但它不是返回内部分配的缓冲区和键长度,而是直接返回在指定上下文 'ctx' 中分配的模块字符串对象(该对象可以像主要 API RedisModule_CreateString
一样为 NULL)。
返回的字符串对象应在使用后被释放,无论是手动释放还是使用具有自动内存管理功能的上下文来释放。
RedisModule_DictPrev
RedisModuleString *RedisModule_DictPrev(RedisModuleCtx *ctx,
RedisModuleDictIter *di,
void **dataptr);
自版本 5.0.0
与 RedisModule_DictNext()
相似,但它在返回迭代器中当前选定的元素之后,选择上一个元素(词法上更小)而不是下一个元素。
RedisModule_DictCompareC
int RedisModule_DictCompareC(RedisModuleDictIter *di,
const char *op,
void *key,
size_t keylen);
自版本 5.0.0
根据运算符 'op'(有效运算符集与 RedisModule_DictIteratorStart
中的有效运算符集相同)将迭代器当前指向的元素与键/keylen 给出的指定元素进行比较。如果比较成功,则命令返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
。
当我们只想发出词法范围时,这很有用,因此在循环中,当我们迭代元素时,我们还可以检查是否仍然在范围内。
如果迭代器到达元素条件的末尾,则该函数返回 REDISMODULE_ERR
。
RedisModule_DictCompare
int RedisModule_DictCompare(RedisModuleDictIter *di,
const char *op,
RedisModuleString *key);
自版本 5.0.0
与 RedisModule_DictCompareC
相似,但将与当前迭代器键进行比较的键作为 RedisModuleString
传递。
模块信息字段
RedisModule_InfoAddSection
int RedisModule_InfoAddSection(RedisModuleInfoCtx *ctx, const char *name);
自版本 6.0.0
用于在添加任何字段之前开始一个新部分。部分名称将以 <modulename>_
为前缀,并且只能包含 A-Z、a-z、0-9。NULL 或空字符串表示使用默认部分(仅 <modulename>
)。当返回值为 REDISMODULE_ERR
时,部分应该并且将被跳过。
RedisModule_InfoBeginDictField
int RedisModule_InfoBeginDictField(RedisModuleInfoCtx *ctx, const char *name);
自版本 6.0.0
开始一个字典字段,类似于 INFO KEYSPACE 中的字段。使用普通的 RedisModule_InfoAddField
* 函数将项目添加到该字段,并使用 RedisModule_InfoEndDictField
结束。
RedisModule_InfoEndDictField
int RedisModule_InfoEndDictField(RedisModuleInfoCtx *ctx);
自版本 6.0.0
结束一个字典字段,请参见 RedisModule_InfoBeginDictField
RedisModule_InfoAddFieldString
int RedisModule_InfoAddFieldString(RedisModuleInfoCtx *ctx,
const char *field,
RedisModuleString *value);
自版本 6.0.0
由 RedisModuleInfoFunc
使用以添加信息字段。每个字段将自动以 <modulename>_
为前缀。字段名称或值不得包含 \r\n
或 :
。
RedisModule_InfoAddFieldCString
int RedisModule_InfoAddFieldCString(RedisModuleInfoCtx *ctx,
const char *field,
const char *value);
自版本 6.0.0
参见 RedisModule_InfoAddFieldString()
.
RedisModule_InfoAddFieldDouble
int RedisModule_InfoAddFieldDouble(RedisModuleInfoCtx *ctx,
const char *field,
double value);
自版本 6.0.0
参见 RedisModule_InfoAddFieldString()
.
RedisModule_InfoAddFieldLongLong
int RedisModule_InfoAddFieldLongLong(RedisModuleInfoCtx *ctx,
const char *field,
long long value);
自版本 6.0.0
参见 RedisModule_InfoAddFieldString()
.
RedisModule_InfoAddFieldULongLong
int RedisModule_InfoAddFieldULongLong(RedisModuleInfoCtx *ctx,
const char *field,
unsigned long long value);
自版本 6.0.0
参见 RedisModule_InfoAddFieldString()
.
RedisModule_RegisterInfoFunc
int RedisModule_RegisterInfoFunc(RedisModuleCtx *ctx, RedisModuleInfoFunc cb);
自版本 6.0.0
注册 INFO 命令的回调。回调应通过调用 RedisModule_InfoAddField*()
函数来添加 INFO 字段。
RedisModule_GetServerInfo
RedisModuleServerInfoData *RedisModule_GetServerInfo(RedisModuleCtx *ctx,
const char *section);
自版本 6.0.0
获取有关服务器的信息,类似于 INFO 命令返回的信息。此函数接受一个可选的 'section' 参数,该参数可以为 NULL。返回值包含输出,可以使用 RedisModule_ServerInfoGetField
等获取各个字段。完成后,需要使用 RedisModule_FreeServerInfo
或启用自动内存管理机制释放它。
RedisModule_FreeServerInfo
void RedisModule_FreeServerInfo(RedisModuleCtx *ctx,
RedisModuleServerInfoData *data);
自版本 6.0.0
释放使用 RedisModule_GetServerInfo()
创建的数据。您需要传递上下文指针 'ctx',仅当字典使用上下文创建而不是传递 NULL 时。
RedisModule_ServerInfoGetField
RedisModuleString *RedisModule_ServerInfoGetField(RedisModuleCtx *ctx,
RedisModuleServerInfoData *data,
const char* field);
自版本 6.0.0
从使用 RedisModule_GetServerInfo()
收集的数据中获取字段的值。您需要传递上下文指针 'ctx',仅当您想使用自动内存机制释放返回的字符串时。如果未找到该字段,则返回值将为 NULL。
RedisModule_ServerInfoGetFieldC
const char *RedisModule_ServerInfoGetFieldC(RedisModuleServerInfoData *data,
const char* field);
自版本 6.0.0
类似于 RedisModule_ServerInfoGetField
,但返回一个 char*,该 char* 不应释放,而是由调用者释放。
RedisModule_ServerInfoGetFieldSigned
long long RedisModule_ServerInfoGetFieldSigned(RedisModuleServerInfoData *data,
const char* field,
int *out_err);
自版本 6.0.0
从使用 RedisModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是数值或超出范围,则返回值将为 0,并且可选的 out_err
参数将设置为 REDISMODULE_ERR
。
RedisModule_ServerInfoGetFieldUnsigned
unsigned long long RedisModule_ServerInfoGetFieldUnsigned(RedisModuleServerInfoData *data,
const char* field,
int *out_err);
自版本 6.0.0
从使用 RedisModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是数值或超出范围,则返回值将为 0,并且可选的 out_err
参数将设置为 REDISMODULE_ERR
。
RedisModule_ServerInfoGetFieldDouble
double RedisModule_ServerInfoGetFieldDouble(RedisModuleServerInfoData *data,
const char* field,
int *out_err);
自版本 6.0.0
从使用 RedisModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是双精度数,则返回值将为 0,并且可选的 out_err
参数将设置为 REDISMODULE_ERR
。
模块实用程序 API
RedisModule_GetRandomBytes
void RedisModule_GetRandomBytes(unsigned char *dst, size_t len);
自版本 5.0.0
使用计数器模式下的 SHA1 返回随机字节,并使用 /dev/urandom 初始化种子。此函数速度很快,因此可以用来生成大量字节,而不会对操作系统的熵池产生任何影响。目前,此函数不是线程安全的。
RedisModule_GetRandomHexChars
void RedisModule_GetRandomHexChars(char *dst, size_t len);
自版本 5.0.0
类似于 RedisModule_GetRandomBytes()
,但不是将字符串设置为随机字节,而是将字符串设置为十六进制字符集 [0-9a-f] 中的随机字符。
模块 API 导出/导入
RedisModule_ExportSharedAPI
int RedisModule_ExportSharedAPI(RedisModuleCtx *ctx,
const char *apiname,
void *func);
自版本 5.0.4
模块调用此函数是为了以给定名称导出某些 API。其他模块可以通过调用对称函数 RedisModule_GetSharedAPI()
并将返回值转换为正确的函数指针来使用此 API。
如果名称尚未被占用,则该函数将返回 REDISMODULE_OK
,否则将返回 REDISMODULE_ERR
,并且不会执行任何操作。
重要:apiname 参数应为具有静态生命周期的字符串文字。API 依赖于这样一个事实,即它将来将始终有效。
RedisModule_GetSharedAPI
void *RedisModule_GetSharedAPI(RedisModuleCtx *ctx, const char *apiname);
自版本 5.0.4
请求导出的 API 指针。返回值只是一个 void 指针,调用此函数的调用者需要将其转换为正确的函数指针,因此这是模块之间的私有约定。
如果请求的 API 不可用,则返回 NULL。由于模块可以在不同的时间以不同的顺序加载,因此此函数的调用应放在某些模块通用的 API 注册步骤中,该步骤在每次模块尝试执行需要外部 API 的命令时被调用:如果某些 API 无法解析,则命令应返回错误。
以下是一个例子
int ... myCommandImplementation(void) {
if (getExternalAPIs() == 0) {
reply with an error here if we cannot have the APIs
}
// Use the API:
myFunctionPointer(foo);
}
而 registerAPI() 函数是
int getExternalAPIs(void) {
static int api_loaded = 0;
if (api_loaded != 0) return 1; // APIs already resolved.
myFunctionPointer = RedisModule_GetSharedAPI("...");
if (myFunctionPointer == NULL) return 0;
return 1;
}
模块命令过滤器 API
RedisModule_RegisterCommandFilter
RedisModuleCommandFilter *RedisModule_RegisterCommandFilter(RedisModuleCtx *ctx,
RedisModuleCommandFilterFunc callback,
int flags);
自版本 5.0.5
注册一个新的命令过滤器函数。
命令过滤使模块可以通过插入所有命令的执行流程来扩展 Redis。
注册的过滤器在 Redis 执行 *任何* 命令之前被调用。这包括核心 Redis 命令和任何模块注册的命令。过滤器适用于所有执行路径,包括
- 由客户端调用。
- 通过
RedisModule_Call()
由任何模块调用。 - 通过 Lua
redis.call()
调用。 - 从主服务器复制命令。
过滤器在特殊的过滤器上下文中执行,该上下文不同于 RedisModuleCtx
,并且更加有限。因为过滤器会影响任何命令,所以必须以非常高效的方式实现它,以减少对 Redis 的性能影响。所有需要有效上下文 (如 RedisModule_Call()
、RedisModule_OpenKey()
等) 的 Redis 模块 API 调用在过滤器上下文中不受支持。
RedisModuleCommandFilterCtx
可用于检查或修改执行的命令及其参数。由于过滤器在 Redis 开始处理命令之前执行,因此任何更改都会影响命令的处理方式。例如,模块可以这样覆盖 Redis 命令
- 注册一个
MODULE.SET
命令,该命令实现 RedisSET
命令的扩展版本。 - 注册一个命令过滤器,该过滤器检测对特定模式的键的
SET
的调用。一旦检测到,过滤器将把第一个参数从SET
替换为MODULE.SET
。 - 当过滤器执行完成后,Redis 会考虑新的命令名称,因此会执行模块自己的命令。
请注意,在上述用例中,如果 MODULE.SET
本身使用 RedisModule_Call()
,则过滤器也会应用于该调用。如果不需要这样做,则可以在注册过滤器时设置 REDISMODULE_CMDFILTER_NOSELF
标志。
REDISMODULE_CMDFILTER_NOSELF
标志可以防止源自模块自身 RedisModule_Call()
的执行流程到达过滤器。此标志对所有执行流程 (包括嵌套流程) 都有效,只要执行始于模块的命令上下文或与阻塞命令关联的线程安全上下文即可。
分离的线程安全上下文*不*与模块关联,无法通过此标志保护。
如果注册了多个过滤器 (由同一模块或不同模块注册),则它们按注册顺序执行。
RedisModule_UnregisterCommandFilter
int RedisModule_UnregisterCommandFilter(RedisModuleCtx *ctx,
RedisModuleCommandFilter *filter);
自版本 5.0.5
注销命令过滤器。
RedisModule_CommandFilterArgsCount
int RedisModule_CommandFilterArgsCount(RedisModuleCommandFilterCtx *fctx);
自版本 5.0.5
返回已过滤命令的参数数量。参数数量包括命令本身。
RedisModule_CommandFilterArgGet
RedisModuleString *RedisModule_CommandFilterArgGet(RedisModuleCommandFilterCtx *fctx,
int pos);
自版本 5.0.5
返回指定的命令参数。第一个参数 (位置 0) 是命令本身,其余是用户提供的参数。
RedisModule_CommandFilterArgInsert
int RedisModule_CommandFilterArgInsert(RedisModuleCommandFilterCtx *fctx,
int pos,
RedisModuleString *arg);
自版本 5.0.5
通过在指定位置插入新参数来修改已过滤的命令。指定的 RedisModuleString
参数可以在过滤器上下文销毁后由 Redis 使用,因此它不能自动内存分配、释放或在其他地方使用。
RedisModule_CommandFilterArgReplace
int RedisModule_CommandFilterArgReplace(RedisModuleCommandFilterCtx *fctx,
int pos,
RedisModuleString *arg);
自版本 5.0.5
通过用新参数替换现有参数来修改已过滤的命令。指定的 RedisModuleString
参数可以在过滤器上下文销毁后由 Redis 使用,因此它不能自动内存分配、释放或在其他地方使用。
RedisModule_CommandFilterArgDelete
int RedisModule_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx,
int pos);
自版本 5.0.5
通过删除指定位置的参数来修改已过滤的命令。
RedisModule_CommandFilterGetClientId
unsigned long long RedisModule_CommandFilterGetClientId(RedisModuleCommandFilterCtx *fctx);
自版本 7.2.0
获取发出我们正在过滤的命令的客户端的客户端 ID
RedisModule_MallocSize
size_t RedisModule_MallocSize(void* ptr);
自版本 6.0.0
对于通过 RedisModule_Alloc()
或 RedisModule_Realloc()
分配的给定指针,返回为其分配的内存量。请注意,这可能与我们使用分配调用分配的内存不同 (更大),因为有时底层分配器会分配更多内存。
RedisModule_MallocUsableSize
size_t RedisModule_MallocUsableSize(void *ptr);
自版本 7.0.1
与 RedisModule_MallocSize
类似,不同之处在于 RedisModule_MallocUsableSize
返回模块可用的内存大小。
RedisModule_MallocSizeString
size_t RedisModule_MallocSizeString(RedisModuleString* str);
自版本 7.0.0
与 RedisModule_MallocSize
相同,除了它适用于 RedisModuleString
指针。
RedisModule_MallocSizeDict
size_t RedisModule_MallocSizeDict(RedisModuleDict* dict);
自版本 7.0.0
与 RedisModule_MallocSize
相同,除了它适用于 RedisModuleDict
指针。请注意,返回值仅是底层结构的开销,不包括键和值的分配大小。
RedisModule_GetUsedMemoryRatio
float RedisModule_GetUsedMemoryRatio(void);
自版本 6.0.0
返回一个介于 0 到 1 之间的数字,表示当前使用的内存量,相对于 Redis 的 "maxmemory" 配置。
- 0 - 未配置内存限制。
- 介于 0 到 1 之间 - 以 0-1 范围归一化的内存使用百分比。
- 正好是 1 - 达到内存限制。
- 大于 1 - 使用的内存超过配置的限制。
扫描键空间和哈希
RedisModule_ScanCursorCreate
RedisModuleScanCursor *RedisModule_ScanCursorCreate(void);
自版本 6.0.0
创建一个新的游标,用于 RedisModule_Scan
RedisModule_ScanCursorRestart
void RedisModule_ScanCursorRestart(RedisModuleScanCursor *cursor);
自版本 6.0.0
重新启动现有游标。键将被重新扫描。
RedisModule_ScanCursorDestroy
void RedisModule_ScanCursorDestroy(RedisModuleScanCursor *cursor);
自版本 6.0.0
销毁游标结构。
RedisModule_Scan
int RedisModule_Scan(RedisModuleCtx *ctx,
RedisModuleScanCursor *cursor,
RedisModuleScanCB fn,
void *privdata);
自版本 6.0.0
扫描 API,允许模块扫描选定 db 中的所有键和值。
扫描实现的回调。
void scan_callback(RedisModuleCtx *ctx, RedisModuleString *keyname,
RedisModuleKey *key, void *privdata);
ctx
: 提供给扫描的 Redis 模块上下文。keyname
: 由调用者拥有,如果在此函数之后使用,则需要保留。key
: 包含有关键和值的的信息,它作为尽力而为提供,在某些情况下它可能是 NULL,在这种情况下,用户应该 (可以) 使用RedisModule_OpenKey()
(以及 CloseKey)。当它被提供时,它由调用者拥有,并且将在回调返回时被释放。privdata
: 提供给RedisModule_Scan()
的用户数据。
使用方法
RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
while(RedisModule_Scan(ctx, c, callback, privateData));
RedisModule_ScanCursorDestroy(c);
还可以从另一个线程使用此 API,同时在实际调用 RedisModule_Scan
时获取锁
RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
RedisModule_ThreadSafeContextLock(ctx);
while(RedisModule_Scan(ctx, c, callback, privateData)){
RedisModule_ThreadSafeContextUnlock(ctx);
// do some background job
RedisModule_ThreadSafeContextLock(ctx);
}
RedisModule_ScanCursorDestroy(c);
如果还有更多元素要扫描,则该函数将返回 1,否则返回 0,如果调用失败,则可能会设置 errno。
还可以使用 RedisModule_ScanCursorRestart
重新启动现有游标。
重要:从其提供的保证的角度来看,此 API 与 Redis SCAN 命令非常相似。这意味着 API 可能会报告重复的键,但保证至少报告一次从扫描过程开始到结束的每个键。
注意:如果在回调中进行数据库更改,则应注意数据库的内部状态可能会发生变化。例如,删除或修改当前键是安全的,但删除任何其他键可能不安全。此外,在迭代时使用 Redis 键空间可能会导致返回更多重复项。一个安全的模式是在别处存储要修改的键名,并在迭代完成后对键执行操作。但是,这可能会占用大量内存,因此,在迭代过程中,只要有可能,就可以直接对当前键进行操作,因为这是安全的。
RedisModule_ScanKey
int RedisModule_ScanKey(RedisModuleKey *key,
RedisModuleScanCursor *cursor,
RedisModuleScanKeyCB fn,
void *privdata);
自版本 6.0.0
扫描 API 允许模块扫描哈希、集合或有序集合键中的元素
扫描实现的回调。
void scan_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata);
- key - 为扫描提供的 Redis 键上下文。
- field - 字段名称,由调用者拥有,如果在该函数之后使用,需要保留。
- value - 值字符串或集合类型的 NULL,由调用者拥有,如果在该函数之后使用,需要保留。
- privdata - 提供给
RedisModule_ScanKey
的用户数据。
使用方法
RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
RedisModuleKey *key = RedisModule_OpenKey(...)
while(RedisModule_ScanKey(key, c, callback, privateData));
RedisModule_CloseKey(key);
RedisModule_ScanCursorDestroy(c);
在实际调用 RedisModule_ScanKey
期间获取锁时,也可以从另一个线程使用此 API,并在每次重新打开键时使用。
RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
RedisModule_ThreadSafeContextLock(ctx);
RedisModuleKey *key = RedisModule_OpenKey(...)
while(RedisModule_ScanKey(ctx, c, callback, privateData)){
RedisModule_CloseKey(key);
RedisModule_ThreadSafeContextUnlock(ctx);
// do some background job
RedisModule_ThreadSafeContextLock(ctx);
RedisModuleKey *key = RedisModule_OpenKey(...)
}
RedisModule_CloseKey(key);
RedisModule_ScanCursorDestroy(c);
如果还有更多元素要扫描,该函数将返回 1,否则返回 0,如果调用失败,可能会设置 errno。也可以使用 RedisModule_ScanCursorRestart
重新启动现有游标。
注意:在迭代对象时,某些操作是不安全的。例如,虽然 API 保证至少一次返回数据结构中始终存在的所有元素,从迭代开始到结束一致地返回(参见 HSCAN 和类似命令文档),但您对元素进行的操作越多,您可能会得到更多重复元素。通常删除数据结构的当前元素是安全的,而删除您正在迭代的键是不安全的。
模块 fork API
RedisModule_Fork
int RedisModule_Fork(RedisModuleForkDoneHandler cb, void *user_data);
自版本 6.0.0
使用主进程当前冻结的快照创建一个后台子进程,您可以在其中进行一些后台处理,而不会影响/冻结流量,并且不需要线程和 GIL 锁定。请注意,Redis 仅允许一个并发 fork。当子进程想要退出时,它应该调用 RedisModule_ExitFromChild
。如果父进程想要杀死子进程,它应该调用 RedisModule_KillForkChild
。当子进程存在(但未被杀死)时,done 处理程序回调将在父进程上执行。返回值:-1 表示失败,成功时父进程将获得子进程的正 PID,子进程将获得 0。
RedisModule_SendChildHeartbeat
void RedisModule_SendChildHeartbeat(double progress);
自版本 6.2.0
建议模块从 fork 子进程中定期调用此函数,以便它可以向父进程报告进度和 COW 内存,这些信息将在 INFO 中报告。progress
参数应介于 0 和 1 之间,或者在不可用时为 -1。
RedisModule_ExitFromChild
int RedisModule_ExitFromChild(int retcode);
自版本 6.0.0
当您想终止子进程时,从子进程中调用。retcode 将提供给在父进程上执行的 done 处理程序。
RedisModule_KillForkChild
int RedisModule_KillForkChild(int child_pid);
自版本 6.0.0
可用于从父进程中杀死 fork 的子进程。child_pid
将是 RedisModule_Fork
的返回值。
服务器钩子实现
RedisModule_SubscribeToServerEvent
int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx,
RedisModuleEvent event,
RedisModuleEventCallback callback);
自版本 6.0.0
注册以通过回调的方式在指定服务器事件发生时收到通知。回调函数使用事件作为参数调用,以及一个额外的参数,该参数是一个 void 指针,应转换为特定类型,该类型是事件特定的(但许多事件将只使用 NULL,因为它们没有额外的信息传递给回调函数)。
如果回调函数为 NULL 并且之前存在订阅,则模块将取消订阅。如果之前存在订阅且回调函数不为空,则旧回调函数将被新回调函数替换。
回调函数必须是这种类型
int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,
RedisModuleEvent eid,
uint64_t subevent,
void *data);
‘ctx’ 是一个普通的 Redis 模块上下文,回调函数可以使用它来调用其他模块的 API。‘eid’ 是事件本身,这仅在模块订阅了多个事件的情况下有用:使用此结构的 ‘id’ 字段,可以检查该事件是否是我们使用此回调函数注册的事件之一。‘subevent’ 字段取决于触发的事件。
最后,‘data’ 指针可能被填充,仅针对某些事件,包含更多相关数据。
以下是您可以用作 ‘eid’ 的事件列表以及相关子事件
-
RedisModuleEvent_ReplicationRoleChanged
:当实例从主服务器切换到从服务器或反过来时,会调用此事件,但是当从服务器保持为从服务器但开始与不同的主服务器复制时,也会调用此事件。
以下子事件可用
REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_MASTER
REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA
‘data’ 字段可以由回调函数转换为
RedisModuleReplicationInfo
结构,该结构具有以下字段int master; // true if master, false if replica char *masterhost; // master instance hostname for NOW_REPLICA int masterport; // master instance port for NOW_REPLICA char *replid1; // Main replication ID char *replid2; // Secondary replication ID uint64_t repl1_offset; // Main replication offset uint64_t repl2_offset; // Offset of replid2 validity
-
RedisModuleEvent_Persistence
当 RDB 保存或 AOF 重写开始和结束时,会调用此事件。以下子事件可用
REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START
REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START
REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START
REDISMODULE_SUBEVENT_PERSISTENCE_ENDED
REDISMODULE_SUBEVENT_PERSISTENCE_FAILED
上述事件不仅在用户调用相关命令(如 BGSAVE)时触发,而且在由于内部服务器触发而导致保存操作或 AOF 重写发生时也会触发。SYNC_RDB_START 子事件是由于 SAVE 命令、FLUSHALL 或服务器关闭而在前台发生的,而其他 RDB 和 AOF 子事件是在后台 fork 子进程中执行的,因此模块采取的任何操作只能影响生成的 AOF 或 RDB,但不会反映在父进程中,也不会影响已连接的客户端和命令。还要注意,AOF_START 子事件最终可能会保存 RDB 内容,以防 AOF 具有 rdb-preamble。
-
RedisModuleEvent_FlushDB
FLUSHALL、FLUSHDB 或内部刷新(例如,由于复制,在从服务器同步之后)发生了。以下子事件可用
REDISMODULE_SUBEVENT_FLUSHDB_START
REDISMODULE_SUBEVENT_FLUSHDB_END
数据指针可以转换为 RedisModuleFlushInfo 结构,该结构具有以下字段
int32_t async; // True if the flush is done in a thread. // See for instance FLUSHALL ASYNC. // In this case the END callback is invoked // immediately after the database is put // in the free list of the thread. int32_t dbnum; // Flushed database number, -1 for all the DBs // in the case of the FLUSHALL operation.
启动事件在操作开始之前调用,因此允许回调函数在待释放的键空间上调用 DBSIZE 或其他操作。
-
RedisModuleEvent_Loading
在加载操作期间调用:在服务器启动时启动时调用,但在从服务器从主服务器加载 RDB 文件后首次同步后也会调用。以下子事件可用
REDISMODULE_SUBEVENT_LOADING_RDB_START
REDISMODULE_SUBEVENT_LOADING_AOF_START
REDISMODULE_SUBEVENT_LOADING_REPL_START
REDISMODULE_SUBEVENT_LOADING_ENDED
REDISMODULE_SUBEVENT_LOADING_FAILED
请注意,AOF 加载可能会以 RDB 数据开头,以防 rdb-preamble,在这种情况下,您只会收到 AOF_START 事件。
-
RedisModuleEvent_ClientChange
当客户端连接或断开连接时调用。数据指针可以转换为 RedisModuleClientInfo 结构,在 RedisModule_GetClientInfoById() 中有文档记录。以下子事件可用
REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED
-
RedisModuleEvent_Shutdown
服务器正在关闭。没有子事件可用。
-
RedisModuleEvent_ReplicaChange
当实例(可以是主服务器或从服务器)获得一个新的在线从服务器或丢失一个从服务器(因为它断开连接)时,会调用此事件。以下子事件可用
REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE
REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE
目前还没有其他信息可用:Redis 的未来版本将有一个 API 用于枚举已连接的从服务器及其状态。
-
RedisModuleEvent_CronLoop
每次 Redis 调用 serverCron() 函数以进行某些簿记时,都会调用此事件。需要定期执行操作的模块可以使用此回调函数。通常,Redis 每秒调用此函数 10 次,但这会根据“hz”配置而改变。没有子事件可用。
数据指针可以转换为 RedisModuleCronLoop 结构,该结构具有以下字段
int32_t hz; // Approximate number of events per second.
-
RedisModuleEvent_MasterLinkChange
这将为从服务器调用,以通知其复制链接何时与我们的主服务器建立功能(正常)连接,或者何时断开连接。请注意,当我们刚刚连接到主服务器时,链接不被视为正常连接,只有在复制正常进行时才会视为正常连接。以下子事件可用
REDISMODULE_SUBEVENT_MASTER_LINK_UP
REDISMODULE_SUBEVENT_MASTER_LINK_DOWN
-
RedisModuleEvent_ModuleChange
当加载新的模块或卸载一个模块时,会调用此事件。以下子事件可用
REDISMODULE_SUBEVENT_MODULE_LOADED
REDISMODULE_SUBEVENT_MODULE_UNLOADED
数据指针可以转换为 RedisModuleModuleChange 结构,该结构具有以下字段
const char* module_name; // Name of module loaded or unloaded. int32_t module_version; // Module version.
-
RedisModuleEvent_LoadingProgress
当 RDB 或 AOF 文件正在加载时,会反复调用此事件。以下子事件可用
REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB
REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF
数据指针可以转换为 RedisModuleLoadingProgress 结构,该结构具有以下字段
int32_t hz; // Approximate number of events per second. int32_t progress; // Approximate progress between 0 and 1024, // or -1 if unknown.
-
RedisModuleEvent_SwapDB
当 SWAPDB 命令成功执行时,会调用此事件。对于此事件调用,目前没有子事件可用。
数据指针可以转换为 RedisModuleSwapDbInfo 结构,该结构具有以下字段
int32_t dbnum_first; // Swap Db first dbnum int32_t dbnum_second; // Swap Db second dbnum
-
RedisModuleEvent_ReplBackup
警告:从 Redis 7.0 开始,复制备份事件已弃用,并且永远不会触发。请参阅 RedisModuleEvent_ReplAsyncLoad 以了解 repl-diskless-load 设置为 swapdb 时如何触发异步复制加载事件。
当 repl-diskless-load 配置设置为 swapdb 时调用,并且 Redis 需要备份当前数据库以备将来可能恢复使用。具有全局数据并且可能具有 aux_load 和 aux_save 回调函数的模块可能需要使用此通知来备份/恢复/丢弃其全局变量。以下子事件可用
REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE
REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE
REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD
-
RedisModuleEvent_ReplAsyncLoad
当 repl-diskless-load 配置设置为 swapdb 并且与具有相同数据集历史记录(匹配复制 ID)的主服务器进行复制时调用。在这种情况下,Redis 会在从套接字中加载新数据库到内存时提供当前数据集。模块必须声明它们支持此机制才能激活它,方法是通过 REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD 标志。以下子事件可用
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED
-
RedisModuleEvent_ForkChild
当 fork 子进程(AOFRW、RDBSAVE、模块 fork...)出生/死亡时调用。以下子事件可用
REDISMODULE_SUBEVENT_FORK_CHILD_BORN
REDISMODULE_SUBEVENT_FORK_CHILD_DIED
-
RedisModuleEvent_EventLoop
在每次事件循环迭代时调用,在事件循环进入休眠状态之前或刚刚醒来之后调用一次。以下子事件可用
REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP
REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP
-
RedisModule_Event_Config
当发生配置事件时调用。以下子事件可用
REDISMODULE_SUBEVENT_CONFIG_CHANGE
数据指针可以转换为 RedisModuleConfigChange 结构,该结构具有以下字段
const char **config_names; // An array of C string pointers containing the // name of each modified configuration item uint32_t num_changes; // The number of elements in the config_names array
-
RedisModule_Event_Key
当从键空间中删除一个键时调用。我们不能在事件中修改任何键。以下子事件可用
REDISMODULE_SUBEVENT_KEY_DELETED
REDISMODULE_SUBEVENT_KEY_EXPIRED
REDISMODULE_SUBEVENT_KEY_EVICTED
REDISMODULE_SUBEVENT_KEY_OVERWRITTEN
数据指针可以转换为 RedisModuleKeyInfo 结构,该结构具有以下字段
RedisModuleKey *key; // Key name
如果模块已成功订阅指定的事件,则该函数返回 REDISMODULE_OK
。如果从错误的上下文中调用 API 或给出了不支持的事件,则返回 REDISMODULE_ERR
。
RedisModule_IsSubEventSupported
int RedisModule_IsSubEventSupported(RedisModuleEvent event, int64_t subevent);
自版本 6.0.9
对于给定的服务器事件和子事件,如果子事件不受支持,则返回零,否则返回非零值。
模块配置 API
RedisModule_RegisterStringConfig
int RedisModule_RegisterStringConfig(RedisModuleCtx *ctx,
const char *name,
const char *default_val,
unsigned int flags,
RedisModuleConfigGetStringFunc getfn,
RedisModuleConfigSetStringFunc setfn,
RedisModuleConfigApplyFunc applyfn,
void *privdata);
自版本 7.0.0
创建一个 Redis 用户可以通过 Redis 配置文件、CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令进行交互的字符串配置。
实际的配置值由模块拥有,以及提供给 Redis 以访问或操作值的 getfn
、setfn
和可选 applyfn
回调。getfn
回调从模块检索值,而 setfn
回调提供要存储到模块配置中的值。可选 applyfn
回调在 CONFIG SET
命令使用 setfn
回调修改了一个或多个配置后被调用,并且可以用于在多个配置一起更改后原子地应用配置。如果单个 CONFIG SET
命令设置了多个具有 applyfn
回调的配置,则如果它们的 applyfn
函数和 privdata
指针相同,它们将被去重,并且回调将只运行一次。setfn
和 applyfn
都可以在提供的 value 无效或无法使用时返回错误。配置还声明了一种由 Redis 验证并提供给模块的值类型。配置系统提供以下类型
- Redis 字符串:二进制安全字符串数据。
- 枚举:在注册期间提供的有限数量的字符串标记之一。
- 数值:64 位带符号整数,也支持最小值和最大值。
- 布尔值:是或否值。
预期 setfn
回调在成功应用值时返回 REDISMODULE_OK
。如果值无法应用,它也可以返回 REDISMODULE_ERR
,并且 *err 指针可以使用 RedisModuleString
错误消息设置以提供给客户端。此 RedisModuleString
将在从 set 回调返回后由 redis 释放。
所有配置都使用名称、类型、默认值、在回调中可用的私有数据以及修改配置行为的几个标志进行注册。名称只能包含字母数字字符或连字符。支持的标志是
REDISMODULE_CONFIG_DEFAULT
:配置的默认标志。这将创建一个可以在启动后修改的配置。REDISMODULE_CONFIG_IMMUTABLE
:此配置只能在加载时提供。REDISMODULE_CONFIG_SENSITIVE
:存储在此配置中的值将从所有日志中删除。REDISMODULE_CONFIG_HIDDEN
:该名称在使用模式匹配的CONFIG GET
中隐藏。REDISMODULE_CONFIG_PROTECTED
:此配置将仅根据 enable-protected-configs 的值进行修改。REDISMODULE_CONFIG_DENY_LOADING
:此配置在服务器加载数据时不可修改。REDISMODULE_CONFIG_MEMORY
:对于数值配置,此配置将把数据单位表示法转换为它们的字节等效值。REDISMODULE_CONFIG_BITFLAGS
:对于枚举配置,此配置将允许将多个条目组合为位标志。
默认值在启动时用于设置值(如果未通过配置文件或命令行提供)。默认值也用于在配置重写时进行比较。
注意
- 在字符串配置集中,传递给 set 回调的字符串将在执行后被释放,模块必须保留它。
- 在字符串配置获取中,字符串不会被使用,并且在执行后仍然有效。
示例实现
RedisModuleString *strval;
int adjustable = 1;
RedisModuleString *getStringConfigCommand(const char *name, void *privdata) {
return strval;
}
int setStringConfigCommand(const char *name, RedisModuleString *new, void *privdata, RedisModuleString **err) {
if (adjustable) {
RedisModule_Free(strval);
RedisModule_RetainString(NULL, new);
strval = new;
return REDISMODULE_OK;
}
*err = RedisModule_CreateString(NULL, "Not adjustable.", 15);
return REDISMODULE_ERR;
}
...
RedisModule_RegisterStringConfig(ctx, "string", NULL, REDISMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL);
如果注册失败,则返回 REDISMODULE_ERR
并且会设置以下 errno 之一
- EBUSY:在
RedisModule_OnLoad
之外注册配置。 - EINVAL:提供的标志对于注册无效,或者配置名称包含无效字符。
- EALREADY:提供的配置名称已在使用。
RedisModule_RegisterBoolConfig
int RedisModule_RegisterBoolConfig(RedisModuleCtx *ctx,
const char *name,
int default_val,
unsigned int flags,
RedisModuleConfigGetBoolFunc getfn,
RedisModuleConfigSetBoolFunc setfn,
RedisModuleConfigApplyFunc applyfn,
void *privdata);
自版本 7.0.0
创建一个布尔配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与之交互。有关配置的详细信息,请参见 RedisModule_RegisterStringConfig
。
RedisModule_RegisterEnumConfig
int RedisModule_RegisterEnumConfig(RedisModuleCtx *ctx,
const char *name,
int default_val,
unsigned int flags,
const char **enum_values,
const int *int_values,
int num_enum_vals,
RedisModuleConfigGetEnumFunc getfn,
RedisModuleConfigSetEnumFunc setfn,
RedisModuleConfigApplyFunc applyfn,
void *privdata);
自版本 7.0.0
创建一个枚举配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与之交互。枚举配置是一组字符串标记到相应整数的值,其中字符串值暴露给 Redis 客户端,但传递给 Redis 和模块的值是整数值。这些值在 enum_values
中定义,enum_values
是一个以空字符结尾的 C 字符串数组,int_vals
是一个枚举值数组,它在 enum_values
中有一个索引伙伴。示例实现:const char *enum_vals[3] = {"first", "second", "third"}; const int int_vals[3] = {0, 2, 4}; int enum_val = 0;
int getEnumConfigCommand(const char *name, void *privdata) {
return enum_val;
}
int setEnumConfigCommand(const char *name, int val, void *privdata, const char **err) {
enum_val = val;
return REDISMODULE_OK;
}
...
RedisModule_RegisterEnumConfig(ctx, "enum", 0, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 3, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);
请注意,您可以使用 REDISMODULE_CONFIG_BITFLAGS
,以便将多个枚举字符串组合成一个整数作为位标志,在这种情况下,您可能需要对枚举进行排序,以便首选组合首先出现。
有关配置的详细信息,请参见 RedisModule_RegisterStringConfig
。
RedisModule_RegisterNumericConfig
int RedisModule_RegisterNumericConfig(RedisModuleCtx *ctx,
const char *name,
long long default_val,
unsigned int flags,
long long min,
long long max,
RedisModuleConfigGetNumericFunc getfn,
RedisModuleConfigSetNumericFunc setfn,
RedisModuleConfigApplyFunc applyfn,
void *privdata);
自版本 7.0.0
创建一个整数配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与之交互。有关配置的详细信息,请参见 RedisModule_RegisterStringConfig
。
RedisModule_LoadConfigs
int RedisModule_LoadConfigs(RedisModuleCtx *ctx);
自版本 7.0.0
应用模块加载时所有待处理的配置。这应该在模块在 RedisModule_OnLoad
内部注册所有配置后调用。如果在 RedisModule_OnLoad
之外调用,则将返回 REDISMODULE_ERR
。当配置在 MODULE LOADEX
中提供或作为启动参数提供时,需要调用此 API。
RDB 加载/保存 API
RedisModule_RdbStreamCreateFromFile
RedisModuleRdbStream *RedisModule_RdbStreamCreateFromFile(const char *filename);
自版本 7.2.0
创建一个流对象以将 RDB 保存/加载到/从文件。
此函数返回指向 RedisModuleRdbStream
的指针,该指针由调用者拥有。它需要调用 RedisModule_RdbStreamFree()
来释放对象。
RedisModule_RdbStreamFree
void RedisModule_RdbStreamFree(RedisModuleRdbStream *stream);
自版本 7.2.0
释放 RDB 流对象。
RedisModule_RdbLoad
int RedisModule_RdbLoad(RedisModuleCtx *ctx,
RedisModuleRdbStream *stream,
int flags);
自版本 7.2.0
从 stream
加载 RDB 文件。数据集将首先被清除,然后加载 RDB 文件。
flags
必须为零。此参数供将来使用。
成功时返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
,并且会相应地设置 errno。
示例
RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
RedisModule_RdbLoad(ctx, s, 0);
RedisModule_RdbStreamFree(s);
RedisModule_RdbSave
int RedisModule_RdbSave(RedisModuleCtx *ctx,
RedisModuleRdbStream *stream,
int flags);
自版本 7.2.0
将数据集保存到 RDB 流。
flags
必须为零。此参数供将来使用。
成功时返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
,并且会相应地设置 errno。
示例
RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
RedisModule_RdbSave(ctx, s, 0);
RedisModule_RdbStreamFree(s);
键驱逐 API
RedisModule_SetLRU
int RedisModule_SetLRU(RedisModuleKey *key, mstime_t lru_idle);
自版本 6.0.0
设置基于 LRU 的驱逐的键最后访问时间。如果服务器的 maxmemory 策略是基于 LFU,则不相关。值为以毫秒为单位的空闲时间。如果 LRU 已更新,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
。
RedisModule_GetLRU
int RedisModule_GetLRU(RedisModuleKey *key, mstime_t *lru_idle);
自版本 6.0.0
获取键的最后访问时间。值为以毫秒为单位的空闲时间,如果服务器的驱逐策略是基于 LFU,则为 -1。如果键有效,则返回 REDISMODULE_OK
。
RedisModule_SetLFU
int RedisModule_SetLFU(RedisModuleKey *key, long long lfu_freq);
自版本 6.0.0
设置键访问频率。如果服务器的 maxmemory 策略是基于 LFU,则仅相关。频率是对数计数器,提供访问频率的指示(必须 <= 255)。如果 LFU 已更新,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
。
RedisModule_GetLFU
int RedisModule_GetLFU(RedisModuleKey *key, long long *lfu_freq);
自版本 6.0.0
获取键访问频率,如果服务器的驱逐策略不是基于 LFU,则返回 -1。如果键有效,则返回 REDISMODULE_OK
。
其他 API
RedisModule_GetModuleOptionsAll
int RedisModule_GetModuleOptionsAll(void);
自版本 7.2.0
返回完整的模块选项标志掩码,使用返回值,模块可以检查正在使用的 redis 服务器版本是否支持某些模块选项集。例子
int supportedFlags = RedisModule_GetModuleOptionsAll();
if (supportedFlags & REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS) {
// REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is supported
} else{
// REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is not supported
}
RedisModule_GetContextFlagsAll
int RedisModule_GetContextFlagsAll(void);
自版本 6.0.9
返回完整的 ContextFlags 掩码,使用返回值,模块可以检查正在使用的 redis 服务器版本是否支持某些标志集。例子
int supportedFlags = RedisModule_GetContextFlagsAll();
if (supportedFlags & REDISMODULE_CTX_FLAGS_MULTI) {
// REDISMODULE_CTX_FLAGS_MULTI is supported
} else{
// REDISMODULE_CTX_FLAGS_MULTI is not supported
}
RedisModule_GetKeyspaceNotificationFlagsAll
int RedisModule_GetKeyspaceNotificationFlagsAll(void);
自版本 6.0.9
返回完整的 KeyspaceNotification 掩码,使用返回值,模块可以检查正在使用的 redis 服务器版本是否支持某些标志集。例子
int supportedFlags = RedisModule_GetKeyspaceNotificationFlagsAll();
if (supportedFlags & REDISMODULE_NOTIFY_LOADED) {
// REDISMODULE_NOTIFY_LOADED is supported
} else{
// REDISMODULE_NOTIFY_LOADED is not supported
}
RedisModule_GetServerVersion
int RedisModule_GetServerVersion(void);
自版本 6.0.9
以 0x00MMmmpp 格式返回 redis 版本。例如,对于 6.0.7,返回值将为 0x00060007。
RedisModule_GetTypeMethodVersion
int RedisModule_GetTypeMethodVersion(void);
自版本 6.2.0
返回 REDISMODULE_TYPE_METHOD_VERSION
的当前 redis-server 运行时值。当调用 RedisModule_CreateDataType
时,您可以使用它来了解 RedisModuleTypeMethods
的哪些字段将被支持,哪些将被忽略。
RedisModule_ModuleTypeReplaceValue
int RedisModule_ModuleTypeReplaceValue(RedisModuleKey *key,
moduleType *mt,
void *new_value,
void **old_value);
自版本 6.0.0
替换分配给模块类型的 value。
键必须打开以供写入,具有现有值,并且具有与调用者指定的类型匹配的 moduleType。
与 RedisModule_ModuleTypeSetValue()
不同,它将释放旧值,此函数仅将旧值与新值交换。
该函数在成功时返回 REDISMODULE_OK
,在错误时返回 REDISMODULE_ERR
,例如
- 键未打开以供写入。
- 键不是模块数据类型键。
- 键是除 'mt' 之外的模块数据类型。
如果 old_value
非空,则旧值将通过引用返回。
RedisModule_GetCommandKeysWithFlags
int *RedisModule_GetCommandKeysWithFlags(RedisModuleCtx *ctx,
RedisModuleString **argv,
int argc,
int *num_keys,
int **out_flags);
自版本 7.0.0
对于指定的命令,解析其参数并返回一个包含所有键名参数索引的数组。此函数本质上是更有效地执行 COMMAND GETKEYS
的方法。
out_flags
参数是可选的,可以设置为 NULL。当提供它时,它将使用与返回数组的键索引匹配的索引中的 REDISMODULE_CMD_KEY_
标志填充。
NULL 返回值表示指定的命令没有键,或者存在错误条件。错误条件通过设置 errno 来指示,如下所示
- ENOENT: 指定的命令不存在。
- EINVAL:指定的命令元数无效。
注意:返回的数组不是 Redis 模块对象,因此即使使用自动内存,它也不会自动释放。调用者必须显式调用 RedisModule_Free()
来释放它,与使用时 out_flags
指针相同。
RedisModule_GetCommandKeys
int *RedisModule_GetCommandKeys(RedisModuleCtx *ctx,
RedisModuleString **argv,
int argc,
int *num_keys);
自版本 6.0.9
与不需要标志时 RedisModule_GetCommandKeysWithFlags
相同。
RedisModule_GetCurrentCommandName
const char *RedisModule_GetCurrentCommandName(RedisModuleCtx *ctx);
自版本 6.2.5
返回当前正在运行的命令的名称
碎片整理 API
RedisModule_RegisterDefragFunc
int RedisModule_RegisterDefragFunc(RedisModuleCtx *ctx,
RedisModuleDefragFunc cb);
自版本 6.2.0
为全局数据注册一个碎片整理回调,即模块可能分配的任何不与特定数据类型绑定的内容。
RedisModule_DefragShouldStop
int RedisModule_DefragShouldStop(RedisModuleDefragCtx *ctx);
自版本 6.2.0
当数据类型碎片整理回调迭代复杂结构时,应该定期调用此函数。零(false)返回值表示回调可以继续其工作。非零值(true)表示它应该停止。
停止后,回调可以使用 RedisModule_DefragCursorSet()
来存储其位置,以便它稍后可以使用 RedisModule_DefragCursorGet()
来恢复碎片整理。
停止后,如果还有更多工作要做,回调应该返回 1。否则,它应该返回 0。
注意:模块应该考虑此函数的调用频率,因此通常在调用之间执行少量工作是有意义的。
RedisModule_DefragCursorSet
int RedisModule_DefragCursorSet(RedisModuleDefragCtx *ctx,
unsigned long cursor);
自版本 6.2.0
存储任意游标值以备将来使用。
这应该只在 RedisModule_DefragShouldStop()
返回非零值并且碎片整理回调将退出而没有完全迭代其数据类型时调用。
此行为保留用于执行延迟碎片整理的情况。延迟碎片整理被选择用于实现 free_effort
回调并返回大于碎片整理 'active-defrag-max-scan-fields' 配置指令的 free_effort
值的键。
较小的键、不实现 free_effort
的键或全局碎片整理回调不会在延迟碎片整理模式下调用。在这些情况下,调用此函数将返回 REDISMODULE_ERR
。
游标可用于模块来表示模块数据类型中的某些进度。模块还可以本地存储额外的游标相关信息,并使用游标作为指示何时开始遍历新键的标志。这是可能的,因为 API 保证不会执行多个键的并发碎片整理。
RedisModule_DefragCursorGet
int RedisModule_DefragCursorGet(RedisModuleDefragCtx *ctx,
unsigned long *cursor);
自版本 6.2.0
获取以前使用 RedisModule_DefragCursorSet()
存储的游标值。
如果未调用延迟碎片整理操作,则会返回REDISMODULE_ERR
,并且应忽略游标。有关碎片整理游标的更多详细信息,请参见RedisModule_DefragCursorSet()
。
RedisModule_DefragAlloc
void *RedisModule_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr);
自版本 6.2.0
碎片整理先前由RedisModule_Alloc
、RedisModule_Calloc
等分配的内存分配。碎片整理过程涉及分配一个新的内存块并将内容复制到其中,就像realloc()
一样。
如果不需要碎片整理,则返回NULL,并且操作没有其他影响。
如果返回非NULL值,则调用者应使用新指针而不是旧指针,并更新对旧指针的任何引用,旧指针不得再次使用。
RedisModule_DefragRedisModuleString
RedisModuleString *RedisModule_DefragRedisModuleString(RedisModuleDefragCtx *ctx,
RedisModuleString *str);
自版本 6.2.0
碎片整理先前由RedisModule_Alloc
、RedisModule_Calloc
等分配的RedisModuleString
。有关碎片整理过程如何工作的更多信息,请参见RedisModule_DefragAlloc()
。
注意:只能对具有单个引用的字符串进行碎片整理。通常这意味着使用RedisModule_RetainString
或RedisModule_HoldString
保留的字符串可能无法进行碎片整理。一个例外是命令argv,如果由模块保留,最终将只有一个引用(因为Redis侧的引用将在命令回调返回后立即删除)。
RedisModule_GetKeyNameFromDefragCtx
const RedisModuleString *RedisModule_GetKeyNameFromDefragCtx(RedisModuleDefragCtx *ctx);
自版本 7.0.0
返回当前正在处理的键的名称。 无法保证键名始终可用,因此这可能会返回 NULL。
RedisModule_GetDbIdFromDefragCtx
int RedisModule_GetDbIdFromDefragCtx(RedisModuleDefragCtx *ctx);
自版本 7.0.0
返回当前正在处理的键的数据库 ID。 无法保证此信息始终可用,因此这可能会返回 -1。
函数索引
RedisModule_ACLAddLogEntry
RedisModule_ACLAddLogEntryByUserName
RedisModule_ACLCheckChannelPermissions
RedisModule_ACLCheckCommandPermissions
RedisModule_ACLCheckKeyPermissions
RedisModule_AbortBlock
RedisModule_AddACLCategory
RedisModule_AddPostNotificationJob
RedisModule_Alloc
RedisModule_AuthenticateClientWithACLUser
RedisModule_AuthenticateClientWithUser
RedisModule_AutoMemory
RedisModule_AvoidReplicaTraffic
RedisModule_BlockClient
RedisModule_BlockClientGetPrivateData
RedisModule_BlockClientOnAuth
RedisModule_BlockClientOnKeys
RedisModule_BlockClientOnKeysWithFlags
RedisModule_BlockClientSetPrivateData
RedisModule_BlockedClientDisconnected
RedisModule_BlockedClientMeasureTimeEnd
RedisModule_BlockedClientMeasureTimeStart
RedisModule_CachedMicroseconds
RedisModule_Call
RedisModule_CallReplyArrayElement
RedisModule_CallReplyAttribute
RedisModule_CallReplyAttributeElement
RedisModule_CallReplyBigNumber
RedisModule_CallReplyBool
RedisModule_CallReplyDouble
RedisModule_CallReplyInteger
RedisModule_CallReplyLength
RedisModule_CallReplyMapElement
RedisModule_CallReplyPromiseAbort
RedisModule_CallReplyPromiseSetUnblockHandler
RedisModule_CallReplyProto
RedisModule_CallReplySetElement
RedisModule_CallReplyStringPtr
RedisModule_CallReplyType
RedisModule_CallReplyVerbatim
RedisModule_Calloc
RedisModule_ChannelAtPosWithFlags
RedisModule_CloseKey
RedisModule_ClusterCanonicalKeyNameInSlot
RedisModule_ClusterKeySlot
RedisModule_CommandFilterArgDelete
RedisModule_CommandFilterArgGet
RedisModule_CommandFilterArgInsert
RedisModule_CommandFilterArgReplace
RedisModule_CommandFilterArgsCount
RedisModule_CommandFilterGetClientId
RedisModule_CreateCommand
RedisModule_CreateDataType
RedisModule_CreateDict
RedisModule_CreateModuleUser
RedisModule_CreateString
RedisModule_CreateStringFromCallReply
RedisModule_CreateStringFromDouble
RedisModule_CreateStringFromLongDouble
RedisModule_CreateStringFromLongLong
RedisModule_CreateStringFromStreamID
RedisModule_CreateStringFromString
RedisModule_CreateStringFromULongLong
RedisModule_CreateStringPrintf
RedisModule_CreateSubcommand
RedisModule_CreateTimer
RedisModule_DbSize
RedisModule_DeauthenticateAndCloseClient
RedisModule_DefragAlloc
RedisModule_DefragCursorGet
RedisModule_DefragCursorSet
RedisModule_DefragRedisModuleString
RedisModule_DefragShouldStop
RedisModule_DeleteKey
RedisModule_DictCompare
RedisModule_DictCompareC
RedisModule_DictDel
RedisModule_DictDelC
RedisModule_DictGet
RedisModule_DictGetC
RedisModule_DictIteratorReseek
RedisModule_DictIteratorReseekC
RedisModule_DictIteratorStart
RedisModule_DictIteratorStartC
RedisModule_DictIteratorStop
RedisModule_DictNext
RedisModule_DictNextC
RedisModule_DictPrev
RedisModule_DictPrevC
RedisModule_DictReplace
RedisModule_DictReplaceC
RedisModule_DictSet
RedisModule_DictSetC
RedisModule_DictSize
RedisModule_DigestAddLongLong
RedisModule_DigestAddStringBuffer
RedisModule_DigestEndSequence
RedisModule_EmitAOF
RedisModule_EventLoopAdd
RedisModule_EventLoopAddOneShot
RedisModule_EventLoopDel
RedisModule_ExitFromChild
RedisModule_ExportSharedAPI
RedisModule_Fork
RedisModule_Free
RedisModule_FreeCallReply
RedisModule_FreeClusterNodesList
RedisModule_FreeDict
RedisModule_FreeModuleUser
RedisModule_FreeServerInfo
RedisModule_FreeString
RedisModule_FreeThreadSafeContext
RedisModule_GetAbsExpire
RedisModule_GetBlockedClientHandle
RedisModule_GetBlockedClientPrivateData
RedisModule_GetBlockedClientReadyKey
RedisModule_GetClientCertificate
RedisModule_GetClientId
RedisModule_GetClientInfoById
RedisModule_GetClientNameById
RedisModule_GetClientUserNameById
RedisModule_GetClusterNodeInfo
RedisModule_GetClusterNodesList
RedisModule_GetClusterSize
RedisModule_GetCommand
RedisModule_GetCommandKeys
RedisModule_GetCommandKeysWithFlags
RedisModule_GetContextFlags
RedisModule_GetContextFlagsAll
RedisModule_GetCurrentCommandName
RedisModule_GetCurrentUserName
RedisModule_GetDbIdFromDefragCtx
RedisModule_GetDbIdFromDigest
RedisModule_GetDbIdFromIO
RedisModule_GetDbIdFromModuleKey
RedisModule_GetDbIdFromOptCtx
RedisModule_GetDetachedThreadSafeContext
RedisModule_GetExpire
RedisModule_GetKeyNameFromDefragCtx
RedisModule_GetKeyNameFromDigest
RedisModule_GetKeyNameFromIO
RedisModule_GetKeyNameFromModuleKey
RedisModule_GetKeyNameFromOptCtx
RedisModule_GetKeyspaceNotificationFlagsAll
RedisModule_GetLFU
RedisModule_GetLRU
RedisModule_GetModuleOptionsAll
RedisModule_GetModuleUserACLString
RedisModule_GetModuleUserFromUserName
RedisModule_GetMyClusterID
RedisModule_GetNotifyKeyspaceEvents
RedisModule_GetOpenKeyModesAll
RedisModule_GetRandomBytes
RedisModule_GetRandomHexChars
RedisModule_GetSelectedDb
RedisModule_GetServerInfo
RedisModule_GetServerVersion
RedisModule_GetSharedAPI
RedisModule_GetThreadSafeContext
RedisModule_GetTimerInfo
RedisModule_GetToDbIdFromOptCtx
RedisModule_GetToKeyNameFromOptCtx
RedisModule_GetTypeMethodVersion
RedisModule_GetUsedMemoryRatio
RedisModule_HashGet
RedisModule_HashSet
RedisModule_HoldString
RedisModule_InfoAddFieldCString
RedisModule_InfoAddFieldDouble
RedisModule_InfoAddFieldLongLong
RedisModule_InfoAddFieldString
RedisModule_InfoAddFieldULongLong
RedisModule_InfoAddSection
RedisModule_InfoBeginDictField
RedisModule_InfoEndDictField
RedisModule_IsBlockedReplyRequest
RedisModule_IsBlockedTimeoutRequest
RedisModule_IsChannelsPositionRequest
RedisModule_IsIOError
RedisModule_IsKeysPositionRequest
RedisModule_IsModuleNameBusy
RedisModule_IsSubEventSupported
RedisModule_KeyAtPos
RedisModule_KeyAtPosWithFlags
RedisModule_KeyExists
RedisModule_KeyType
RedisModule_KillForkChild
RedisModule_LatencyAddSample
RedisModule_ListDelete
RedisModule_ListGet
RedisModule_ListInsert
RedisModule_ListPop
RedisModule_ListPush
RedisModule_ListSet
RedisModule_LoadConfigs
RedisModule_LoadDataTypeFromString
RedisModule_LoadDataTypeFromStringEncver
RedisModule_LoadDouble
RedisModule_LoadFloat
RedisModule_LoadLongDouble
RedisModule_LoadSigned
RedisModule_LoadString
RedisModule_LoadStringBuffer
RedisModule_LoadUnsigned
RedisModule_Log
RedisModule_LogIOError
RedisModule_MallocSize
RedisModule_MallocSizeDict
RedisModule_MallocSizeString
RedisModule_MallocUsableSize
RedisModule_Microseconds
RedisModule_Milliseconds
RedisModule_ModuleTypeGetType
RedisModule_ModuleTypeGetValue
RedisModule_ModuleTypeReplaceValue
RedisModule_ModuleTypeSetValue
RedisModule_MonotonicMicroseconds
RedisModule_NotifyKeyspaceEvent
RedisModule_OpenKey
RedisModule_PoolAlloc
RedisModule_PublishMessage
RedisModule_PublishMessageShard
RedisModule_RandomKey
RedisModule_RdbLoad
RedisModule_RdbSave
RedisModule_RdbStreamCreateFromFile
RedisModule_RdbStreamFree
RedisModule_Realloc
RedisModule_RedactClientCommandArgument
RedisModule_RegisterAuthCallback
RedisModule_RegisterBoolConfig
RedisModule_RegisterClusterMessageReceiver
RedisModule_RegisterCommandFilter
RedisModule_RegisterDefragFunc
RedisModule_RegisterEnumConfig
RedisModule_RegisterInfoFunc
RedisModule_RegisterNumericConfig
RedisModule_RegisterStringConfig
RedisModule_Replicate
RedisModule_ReplicateVerbatim
RedisModule_ReplySetArrayLength
RedisModule_ReplySetAttributeLength
RedisModule_ReplySetMapLength
RedisModule_ReplySetSetLength
RedisModule_ReplyWithArray
RedisModule_ReplyWithAttribute
RedisModule_ReplyWithBigNumber
RedisModule_ReplyWithBool
RedisModule_ReplyWithCString
RedisModule_ReplyWithCallReply
RedisModule_ReplyWithDouble
RedisModule_ReplyWithEmptyArray
RedisModule_ReplyWithEmptyString
RedisModule_ReplyWithError
RedisModule_ReplyWithErrorFormat
RedisModule_ReplyWithLongDouble
RedisModule_ReplyWithLongLong
RedisModule_ReplyWithMap
RedisModule_ReplyWithNull
RedisModule_ReplyWithNullArray
RedisModule_ReplyWithSet
RedisModule_ReplyWithSimpleString
RedisModule_ReplyWithString
RedisModule_ReplyWithStringBuffer
RedisModule_ReplyWithVerbatimString
RedisModule_ReplyWithVerbatimStringType
RedisModule_ResetDataset
RedisModule_RetainString
RedisModule_SaveDataTypeToString
RedisModule_SaveDouble
RedisModule_SaveFloat
RedisModule_SaveLongDouble
RedisModule_SaveSigned
RedisModule_SaveString
RedisModule_SaveStringBuffer
RedisModule_SaveUnsigned
RedisModule_Scan
RedisModule_ScanCursorCreate
RedisModule_ScanCursorDestroy
RedisModule_ScanCursorRestart
RedisModule_ScanKey
RedisModule_SelectDb
RedisModule_SendChildHeartbeat
RedisModule_SendClusterMessage
RedisModule_ServerInfoGetField
RedisModule_ServerInfoGetFieldC
RedisModule_ServerInfoGetFieldDouble
RedisModule_ServerInfoGetFieldSigned
RedisModule_ServerInfoGetFieldUnsigned
RedisModule_SetAbsExpire
RedisModule_SetClientNameById
RedisModule_SetClusterFlags
RedisModule_SetCommandACLCategories
RedisModule_SetCommandInfo
RedisModule_SetContextUser
RedisModule_SetDisconnectCallback
RedisModule_SetExpire
RedisModule_SetLFU
RedisModule_SetLRU
RedisModule_SetModuleOptions
RedisModule_SetModuleUserACL
RedisModule_SetModuleUserACLString
RedisModule_SignalKeyAsReady
RedisModule_SignalModifiedKey
RedisModule_StopTimer
RedisModule_Strdup
RedisModule_StreamAdd
RedisModule_StreamDelete
RedisModule_StreamIteratorDelete
RedisModule_StreamIteratorNextField
RedisModule_StreamIteratorNextID
RedisModule_StreamIteratorStart
RedisModule_StreamIteratorStop
RedisModule_StreamTrimByID
RedisModule_StreamTrimByLength
RedisModule_StringAppendBuffer
RedisModule_StringCompare
RedisModule_StringDMA
RedisModule_StringPtrLen
RedisModule_StringSet
RedisModule_StringToDouble
RedisModule_StringToLongDouble
RedisModule_StringToLongLong
RedisModule_StringToStreamID
RedisModule_StringToULongLong
RedisModule_StringTruncate
RedisModule_SubscribeToKeyspaceEvents
RedisModule_SubscribeToServerEvent
RedisModule_ThreadSafeContextLock
RedisModule_ThreadSafeContextTryLock
RedisModule_ThreadSafeContextUnlock
RedisModule_TrimStringAllocation
RedisModule_TryAlloc
RedisModule_TryCalloc
RedisModule_TryRealloc
RedisModule_UnblockClient
RedisModule_UnlinkKey
RedisModule_UnregisterCommandFilter
RedisModule_ValueLength
RedisModule_WrongArity
RedisModule_Yield
RedisModule_ZsetAdd
RedisModule_ZsetFirstInLexRange
RedisModule_ZsetFirstInScoreRange
RedisModule_ZsetIncrby
RedisModule_ZsetLastInLexRange
RedisModule_ZsetLastInScoreRange
RedisModule_ZsetRangeCurrentElement
RedisModule_ZsetRangeEndReached
RedisModule_ZsetRangeNext
RedisModule_ZsetRangePrev
RedisModule_ZsetRangeStop
RedisModule_ZsetRem
RedisModule_ZsetScore
RedisModule__Assert