模块 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
- 模块 EventLoop 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 memory 中报告,根据 maxmemory 设置用于键逐出,并且通常被视为 Redis 分配的内存。您应该避免使用 malloc()
。如果无法分配足够的内存,此函数会发生 panic。
RedisModule_TryAlloc
void *RedisModule_TryAlloc(size_t bytes);
可用版本 7.0.0
与 RedisModule_Alloc
类似,但在分配失败时返回 NULL,而不是发生 panic。
RedisModule_Calloc
void *RedisModule_Calloc(size_t nmemb, size_t size);
可用版本 4.0.0
像 calloc()
一样使用。使用此函数分配的内存会在 Redis INFO memory 中报告,根据 maxmemory 设置用于键逐出,并且通常被视为 Redis 分配的内存。您应该避免直接使用 calloc()
。
RedisModule_TryCalloc
void *RedisModule_TryCalloc(size_t nmemb, size_t size);
可用版本 7.4.0
与 RedisModule_Calloc
类似,但在分配失败时返回 NULL,而不是发生 panic。
RedisModule_Realloc
void* RedisModule_Realloc(void *ptr, size_t bytes);
可用版本 4.0.0
对通过 RedisModule_Alloc()
获取的内存像 realloc()
一样使用。
RedisModule_TryRealloc
void *RedisModule_TryRealloc(void *ptr, size_t bytes);
可用版本 7.4.0
与 RedisModule_Realloc
类似,但在分配失败时返回 NULL,而不是发生 panic。
RedisModule_Free
void RedisModule_Free(void *ptr);
可用版本 4.0.0
对通过 RedisModule_Alloc()
和 RedisModule_Realloc()
获取的内存像 free()
一样使用。但是,您绝不应该尝试使用 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/docs/latest/develop/reference/modules/。
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);
}
注意:在上面的示例中,get keys API 可以通过 key-specs 处理(首选)。仅当无法声明覆盖所有键的 key-specs 时,才需要实现 getkeys-api。
RedisModule_KeyAtPos
void RedisModule_KeyAtPos(RedisModuleCtx *ctx, int pos);
可用版本 4.0.0
此 API 在添加 RedisModule_KeyAtPosWithFlags
之前就已存在,现已弃用,可用于兼容旧版本,即在引入 key-specs 和 flags 之前。
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":命令在 Pub/Sub 频道上发布内容。
- "random":即使输入参数和键值相同,命令也可能有不同的输出。从 Redis 7.0 开始,此标志已被弃用。可以使用命令提示将命令声明为“random”,参见 https://redis.ac.cn/docs/latest/develop/reference/command-tips/。
- "allow-stale":允许在不提供过时数据的从服务器上运行此命令。如果您不确定这意味着什么,请勿使用此标志。
- "no-monitor":不在 monitor 上传播命令。如果命令参数包含敏感数据,请使用此标志。
- "no-slowlog":不在 slowlog 中记录此命令。如果命令参数包含敏感数据,请使用此标志。
- "fast":命令的时间复杂度不大于 O(log(N)),其中 N 是集合的大小或任何表示命令正常可伸缩性问题的其他因素。
- "getkeys-api":命令实现了返回作为键的参数的接口。当由于命令语法原因,start/stop/step 不足时使用。
- "no-cluster":命令不应在 Redis Cluster 中注册,因为它不设计用于集群模式,例如,无法报告键的位置、程序化创建键名或任何其他原因。
- "no-auth":此命令可由未经身份验证的客户端运行。通常用于验证客户端的命令会使用此标志。
- "may-replicate":此命令可能产生复制流量,即使它不是写入命令。
- "no-mandatory-keys":此命令可能需要的所有键都是可选的
- "blocking":命令有可能阻塞客户端。
- "allow-busy":允许在服务器被脚本或慢速模块命令阻塞时执行此命令,参见 RedisModule_Yield。
- "getchannels-api":命令实现了返回作为频道的参数的接口。
- "internal":内部命令,不应暴露给用户连接。例如,模块调用的模块命令、不执行 ACL 验证(依赖于先前的检查)的命令。
最后三个参数指定新命令的哪些参数是 Redis 键。更多信息请参见 https://redis.ac.cn/commands/command。
firstkey
:第一个作为键的参数的从 1 开始的索引。位置 0 始终是命令名称本身。对于没有键的命令,此值为 0。lastkey
:最后一个作为键的参数的从 1 开始的索引。负数表示从最后一个参数向后计数(-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' 将命令标记为 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/docs/latest/develop/reference/command-tips/。 -
arity
:参数数量,包括命令名称本身。正数指定确切的参数数量,负数指定最小参数数量,因此使用 -N 表示 >= N。Redis 在将调用传递给模块之前会进行验证,因此这可以替代模块命令实现中的参数数量检查。如果命令有子命令,值为 0(或省略 arity 字段)等同于 -2,否则等同于 -1。 -
key_specs
:RedisModuleCommandKeySpec
数组,以一个清零的元素终止。这是一个试图比旧的RedisModule_CreateCommand
参数firstkey
,lastkey
,keystep
更好地描述键参数位置的方案,如果那三个参数不足以描述键位置,则需要使用此方案。检索键位置有两个步骤:开始搜索 (BS),在该步骤中应找到第一个键;以及 查找键 (FK),该步骤相对于 BS 的输出,描述了我们如何确定哪些参数是键。此外,还有键特定的标志。键规范导致在 RedisModule_CreateCommand 中给定的三元组 (firstkey, lastkey, keystep) 被重新计算,但在 RedisModule_CreateCommand 中提供这三个参数仍然有用,以便更好地支持 RedisModule_SetCommandInfo 不可用的旧 Redis 版本。
请注意,key-specs 并未完全取代 "getkeys-api"(参见 RedisModule_CreateCommand, RedisModule_IsKeysPositionRequest 和 RedisModule_KeyAtPosWithFlags),因此同时提供 key-specs 并实现 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
:这是一个联合体 (union),其中的index
或keyword
分支根据begin_search_type
字段的值使用。-
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
:这是一个联合体 (union),其中的range
或keynum
分支根据find_keys_type
字段的值使用。-
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)的逻辑操作,即被使用/返回/复制/更改。它不涉及元数据的修改或返回(如类型、计数、数据存在性)。ACCESS 可以与 INSERT、DELETE 或 UPDATE 中的一个写入操作结合使用。任何非 INSERT 或 DELETE 的写入都将被视为 UPDATE。
-
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
数组,以一个清零的元素终止。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。标志是以下各项的位掩码:
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()
调用(它只是自动执行)。
通常,当以下条件同时为真时,您需要调用此函数:
- 您已启用自动内存管理。
- 您想创建字符串对象。
- 您创建的那些字符串对象需要在创建它们的 callback 函数(例如命令实现)返回后继续存在。
通常您希望这样做是为了将创建的字符串对象存储到您自己的数据结构中,例如在实现新的数据类型时。
请注意,当内存管理关闭时,您不需要调用 RetainString(),因为创建字符串总会导致在 callback 函数返回后仍然存在的字符串,前提是没有执行 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
将字符串转换为 double,存储在 *d
中。成功时返回 REDISMODULE_OK
,如果字符串不是 double 值的有效字符串表示,则返回 REDISMODULE_ERR
。
RedisModule_StringToLongDouble
int RedisModule_StringToLongDouble(const RedisModuleString *str,
long double *ld);
可用版本 6.0.0
将字符串转换为 long double,存储在 *ld
中。成功时返回 REDISMODULE_OK
,如果字符串不是 double 值的有效字符串表示,则返回 REDISMODULE_ERR
。
RedisModule_StringToStreamID
int RedisModule_StringToStreamID(const RedisModuleString *str,
RedisModuleStreamID *id);
可用版本 6.2.0
将字符串转换为流 ID,存储在 *id
中。成功时返回 REDISMODULE_OK
,如果字符串不是流 ID 的有效字符串表示,则返回 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*
风格的函数以发出集合的元素。集合类型包括:Array、Map、Set 和 Attribute。
当生成元素数量未知集合时,函数可以带特殊标志 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”个元素的数组类型。
开始数组回复后,模块必须调用 len
次其他 ReplyWith*
风格的函数以发出数组的元素。有关更多详细信息,请参阅回复 API 部分。
使用 RedisModule_ReplySetArrayLength()
设置延迟长度。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithMap
int RedisModule_ReplyWithMap(RedisModuleCtx *ctx, long len);
可用版本 7.0.0
回复一个包含“len”对的 RESP3 Map 类型。访问 https://github.com/antirez/RESP3/blob/master/spec.md 了解更多关于 RESP3 的信息。
开始 Map 回复后,模块必须调用 len*2
次其他 ReplyWith*
风格的函数以发出 Map 的元素。有关更多详细信息,请参阅回复 API 部分。
如果连接的客户端使用 RESP2,回复将被转换为一个扁平数组。
使用 RedisModule_ReplySetMapLength()
设置延迟长度。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithSet
int RedisModule_ReplyWithSet(RedisModuleCtx *ctx, long len);
可用版本 7.0.0
回复一个包含“len”个元素的 RESP3 Set 类型。访问 https://github.com/antirez/RESP3/blob/master/spec.md 了解更多关于 RESP3 的信息。
开始 Set 回复后,模块必须调用 len
次其他 ReplyWith*
风格的函数以发出 Set 的元素。有关更多详细信息,请参阅回复 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
开始属性回复后,模块必须调用 len*2
次其他 ReplyWith*
风格的函数以发出属性 Map 的元素。有关更多详细信息,请参阅回复 API 部分。
使用 RedisModule_ReplySetAttributeLength()
设置延迟长度。
RESP2 不支持此功能,将返回 REDISMODULE_ERR
,否则该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithNullArray
int RedisModule_ReplyWithNullArray(RedisModuleCtx *ctx);
可用版本 6.0.0
向客户端回复一个 null 数组,在 RESP3 中只是 null,在 RESP2 中是 null 数组。
注意:在 RESP3 中,Null 回复和 NullArray 回复之间没有区别,因此为了避免歧义,最好避免使用此 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_ReplyWithArray()
与参数 REDISMODULE_POSTPONED_LEN
一起使用时(因为我们事先不知道将作为数组元素输出的项数),此函数将负责设置数组长度。
由于可能存在多个带有未知长度的待定数组回复,此函数保证始终设置以延迟方式创建的最新数组的长度。
例如,为了输出一个像 [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
应恰好是 Map 上下文中调用 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
回复一个 bulk string,输入为一个 C 缓冲区指针和长度。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithCString
int RedisModule_ReplyWithCString(RedisModuleCtx *ctx, const char *buf);
可用版本 5.0.6
回复一个 bulk string,输入为一个假定为 null 结尾的 C 缓冲区指针。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithString
int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);
可用版本 4.0.0
回复一个 bulk string,输入为一个 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 中,这是 "1" 和 "0" 的字符串响应,分别表示 true 和 false。
该函数始终返回 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 Double 类型。访问 https://github.com/antirez/RESP3/blob/master/spec.md 了解更多关于 RESP3 的信息。
发送通过将 double 'd' 转换为 bulk string 获得的字符串回复。此函数基本上等效于将 double 转换为 C 缓冲区中的字符串,然后使用该缓冲区和长度调用函数 RedisModule_ReplyWithStringBuffer()
。
在 RESP3 中,该字符串被标记为 double,而在 RESP2 中,它只是一个普通字符串,用户必须自己解析。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithBigNumber
int RedisModule_ReplyWithBigNumber(RedisModuleCtx *ctx,
const char *bignum,
size_t len);
可用版本 7.0.0
回复一个 RESP3 BigNumber 类型。访问 https://github.com/antirez/RESP3/blob/master/spec.md 了解更多关于 RESP3 的信息。
在 RESP3 中,这是一个长度为 len
且标记为 BigNumber 的字符串,但是,调用者负责确保它是一个有效的 BigNumber。在 RESP2 中,这只是一个普通的 bulk string 响应。
该函数始终返回 REDISMODULE_OK
。
RedisModule_ReplyWithLongDouble
int RedisModule_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld);
可用版本 6.0.0
发送通过将 long double 'ld' 转换为 bulk string 获得的字符串回复。此函数基本上等效于将 long double 转换为 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 中,按执行顺序排列。
模块应尝试使用其中一个接口。
此命令与 RedisModule_Call()
遵循完全相同的接口,因此必须传递一组格式说明符,后跟与提供的格式说明符匹配的参数。
有关更多信息,请参考 RedisModule_Call()
。
使用特殊的“A”和“R”修饰符,调用者可以从指定命令的传播中排除 AOF 或副本。否则,默认情况下,命令将在两个通道中传播。
关于从线程安全上下文调用此函数的注意事项
通常,当您从实现模块命令的回调或 Redis Module API 提供的任何其他回调中调用此函数时,Redis 将在回调的上下文中累积所有对此函数的调用,并将所有命令包装在 MULTI/EXEC 事务中进行传播。但是,当从可以存活未定义时间量且可以随意锁定/解锁的线程安全上下文调用此函数时,重要的是要注意此 API 非线程安全,并且必须在持有 GIL 时执行。
返回值
如果格式说明符无效或命令名称不属于已知命令,则命令返回 REDISMODULE_ERR
。
RedisModule_ReplicateVerbatim
int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx);
可用版本 4.0.0
此函数将完全按照客户端调用的方式复制命令。请注意,复制的命令总是被包装在包含给定模块命令执行中所有复制命令的 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
指针不为 NULL,而是指向之前使用正确的 REDISMODULE_CLIENTINFO_INITIALIZER_V1
初始化的 RedisModuleClientInfoV1
类型结构体时,该结构体将填充以下字段:
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
返回当前选定的数据库。
RedisModule_GetContextFlags
int RedisModule_GetContextFlags(RedisModuleCtx *ctx);
可用版本 4.0.3
返回当前上下文的标志。这些标志提供当前请求上下文的信息(客户端是 Lua 脚本还是在 MULTI 事务中),以及关于 Redis 实例的总体信息,即复制和持久化。
即使上下文为 NULL,也可以调用此函数,但在此情况下,以下标志将不会被报告:
- 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
: 实例设置了最大内存 -
REDISMODULE_CTX_FLAGS_EVICT
: 设置了最大内存,并且有可能会删除键的驱逐策略 -
REDISMODULE_CTX_FLAGS_OOM
: 根据最大内存设置,Redis 内存不足。 -
REDISMODULE_CTX_FLAGS_OOM_WARNING
: 在达到最大内存水平之前,剩余内存不足 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_CTX_FLAGS_DEBUG_ENABLED
: 此上下文启用了调试命令。
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
更改当前选定的数据库。如果 ID 超出范围,则返回错误。
请注意,即使调用此函数的模块实现的 Redis 命令返回后,客户端仍将保留当前选定的数据库。
如果模块命令希望在另一个数据库中更改某些内容并返回到原始数据库,它应该在此之前调用 RedisModule_GetSelectedDb()
,以便在返回之前恢复旧的数据库编号。
RedisModule_KeyExists
int RedisModule_KeyExists(RedisModuleCtx *ctx, robj *keyname);
可用版本 7.0.0
检查键是否存在,而不影响其最后访问时间。
这等效于调用 RedisModule_OpenKey
,模式为 REDISMODULE_READ
| REDISMODULE_OPEN_KEY_NOTOUCH
,然后检查是否返回 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()
仍然是安全的。
可以通过 mode 参数传递给 API 的额外标志
REDISMODULE_OPEN_KEY_NOTOUCH
- 打开键时避免触碰其 LRU/LFU 信息。REDISMODULE_OPEN_KEY_NONOTIFY
- 键未命中时不触发键空间事件。REDISMODULE_OPEN_KEY_NOSTATS
- 不更新键空间命中/未命中计数器。REDISMODULE_OPEN_KEY_NOEXPIRE
- 避免删除惰性过期的键。REDISMODULE_OPEN_KEY_NOEFFECTS
- 避免获取键产生任何副作用。REDISMODULE_OPEN_KEY_ACCESS_EXPIRED
- 访问尚未删除的过期键
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
返回键的类型。如果键指针为 NULL,则返回 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 时,数据库内容将由后台线程释放。
RedisModule_DbSize
unsigned long long RedisModule_DbSize(RedisModuleCtx *ctx);
可用版本 6.0.0
返回当前数据库中的键数量。
RedisModule_RandomKey
RedisModuleString *RedisModule_RandomKey(RedisModuleCtx *ctx);
可用版本 6.0.0
返回一个随机键的名称,如果当前数据库为空则返回 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
返回当前正在处理的数据库 ID。
RedisModule_GetToDbIdFromOptCtx
int RedisModule_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);
可用版本 7.0.0
返回当前正在处理的目标数据库 ID。
字符串类型的键 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” 是由以下标志通过位或运算组成的
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
,即键未打开以供写入、不是字符串或请求的大小超过 512MB。
如果键为空,则创建一个字符串类型的键,其值为新的字符串值,除非请求的新长度为零。
列表类型的键 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
:
- 如果 key 或 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
:
- 如果 key 为 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
:
- 如果 key 为 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
:
- 如果 key 或 value 为 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
:
- 如果 key 或 value 为 NULL,则为 EINVAL。
- 如果键的类型不是列表,则为 ENOTSUP。
- 如果键未打开以供写入,则为 EBADF。
- 如果索引在列表中不是有效索引,则为 EDOM。
RedisModule_ListDelete
int RedisModule_ListDelete(RedisModuleKey *key, long index);
可用版本 7.0.0
删除给定索引处的元素。索引是基于 0 的。也可以使用负索引,从列表末尾开始计数。
成功时返回 REDISMODULE_OK
。失败时返回 REDISMODULE_ERR
并按如下方式设置 errno
:
- 如果 key 或 value 为 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' 参数,如果为 true,则分别设置一个范围,其中最小值和最大值是排他的(不包含),而不是包含的。
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 选项,详见后文)。在字段/值指针对的末尾,必须指定 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 开始):
- 如果设置了任何未知标志或 key 为 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。在字段/值指针对的末尾,必须指定 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
: 字段名作为以 null 结尾的 C 字符串。
REDISMODULE_HASH_EXISTS
: 函数不期望设置字段的值(即不需要指向 RedisModuleString
指针的指针),而只是报告字段是否存在,并期望一个整数指针作为每对的第二个元素。
REDISMODULE_HASH_EXPIRE_TIME
: 检索哈希中字段的过期时间。函数期望一个 mstime_t
指针作为每对的第二个元素。如果字段不存在或没有过期时间,则将值设置为 REDISMODULE_NO_EXPIRE
。此标志不能与 REDISMODULE_HASH_EXISTS
一起使用。
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,"username",&exists,NULL);
REDISMODULE_HASH_EXPIRE_TIME
示例:
mstime_t hpExpireTime;
RedisModule_HashGet(mykey,REDISMODULE_HASH_EXPIRE_TIME,"hp",&hpExpireTime,NULL);
函数成功时返回 REDISMODULE_OK
,如果键不是哈希值则返回 REDISMODULE_ERR
。
内存管理
返回的 RedisModuleString
对象应使用 RedisModule_FreeString()
释放,或通过启用自动内存管理。
RedisModule_HashFieldMinExpire
mstime_t RedisModule_HashFieldMinExpire(RedisModuleKey *key);
可用版本: 未发布
检索哈希中字段的最小过期时间。
返回值
- 如果至少一个字段设置了过期时间,则返回哈希字段的最小过期时间(以毫秒为单位)。
- 如果没有任何字段设置过期时间或键不是哈希,则返回
REDISMODULE_NO_EXPIRE
。
流类型的键 API
有关流(Streams)的介绍,请参见 https://redis.ac.cn/docs/latest/develop/data-types/streams/。
流函数中使用的类型 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
但您不关心接收 ID,则可以为 NULL。如果未设置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()
打开以供读取的流键。标志
:REDISMODULE_STREAM_ITERATOR_EXCLUSIVE
: 迭代范围不包含start
和end
。REDISMODULE_STREAM_ITERATOR_REVERSE
: 反向迭代,从范围的end
开始。
start
: 范围的下限。对于流的开头,使用 NULL。end
: 范围的上限。对于流的末尾,使用 NULL。
成功时返回 REDISMODULE_OK
。失败时返回 REDISMODULE_ERR
并按如下方式设置 errno
:
- 如果使用无效参数调用,则为 EINVAL
- 如果键引用的值类型不是流或键为空,则为 ENOTSUP
- 如果键未打开以供写入或键已关联流迭代器,则为 EBADF
- 如果
start
或end
超出有效范围,则为 EDOM
成功时返回 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
:
- 如果使用 NULL 键调用,则为 EINVAL
- 如果键引用的值类型不是流或键为空,则为 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
:
- 如果使用 NULL 键调用,则为 EINVAL
- 如果键引用的值类型不是流或键为空,则为 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
:
- 如果使用 NULL 键调用,则为 EINVAL
- 如果键引用的值类型不是流或键为空,则为 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
- 如果键为空或类型不是流,则为 ENOTSUP
- 如果键未打开以供写入,或者未启动迭代器,则为 EBADF
- 如果迭代器没有当前流条目,则为 ENOENT
RedisModule_StreamTrimByLength
long long RedisModule_StreamTrimByLength(RedisModuleKey *key,
int flags,
long long length);
可用版本 6.2.0
按长度修剪流,类似于带有 MAXLEN 的 XTRIM。
key
: 为写入而打开的键。flags
: 一个位域,包含:REDISMODULE_STREAM_TRIM_APPROX
: 如果能提升性能则少量修剪,类似于带有~
修饰符的 XTRIM。
length
: 修剪后要保留的流条目数量。
返回删除的条目数量。失败时返回一个负值,并按如下方式设置 errno
:
- 如果使用无效参数调用,则为 EINVAL
- 如果键为空或类型不是 stream,则返回 ENOTSUP
- 如果键未为写入打开,则返回 EBADF
RedisModule_StreamTrimByID
long long RedisModule_StreamTrimByID(RedisModuleKey *key,
int flags,
RedisModuleStreamID *id);
可用版本 6.2.0
按 ID 修剪 stream,类似于带有 MINID 的 XTRIM。
key
: 为写入而打开的键。flags
: 一个位域,包含:REDISMODULE_STREAM_TRIM_APPROX
: 如果能提升性能则少量修剪,类似于带有~
修饰符的 XTRIM。
id
: 修剪后要保留的最小 stream ID。
返回删除的条目数量。失败时返回一个负值,并按如下方式设置 errno
:
- 如果使用无效参数调用,则为 EINVAL
- 如果键为空或类型不是 stream,则返回 ENOTSUP
- 如果键未为写入打开,则返回 EBADF
从模块调用 Redis 命令
RedisModule_Call()
将命令发送到 Redis。其余函数处理回复。
RedisModule_FreeCallReply
void RedisModule_FreeCallReply(RedisModuleCallReply *reply);
可用版本 4.0.0
释放一个 Call 回复,如果它是数组,则释放其包含的所有嵌套回复。
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
返回 double 回复的 double 值。
RedisModule_CallReplyBigNumber
const char *RedisModule_CallReplyBigNumber(RedisModuleCallReply *reply,
size_t *len);
可用版本 7.0.0
返回 big number 回复的 big number 值。
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
检索 map 回复中第 '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
上设置 unblock 处理程序(回调和私有数据)。给定的回复必须是 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
' 提供的私有数据的值,以便调用方能够释放私有数据。
如果执行成功中止,则保证不会调用 unblock 处理程序。话虽如此,中止操作仍有可能成功但操作继续进行。例如,如果模块实现了某个阻塞命令并且不尊重断开连接回调,就可能发生这种情况。对于纯 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 返回一个 map 而不是扁平数组。 -
0
-- 在自动模式下返回回复,即回复格式将与附加到给定 RedisModuleCtx 的客户端相同。当您想直接将回复传递给客户端时,可能会使用此选项。 -
C
-- 以附加到上下文的用户身份运行命令。用户要么通过直接发出命令并创建上下文的客户端自动附加,要么通过 RedisModule_SetContextUser 设置。如果上下文不是由发出的命令直接创建的(例如后台上下文且未通过 RedisModule_SetContextUser 设置用户),则 RedisModule_Call 将失败。检查命令是否可以根据 ACL 规则执行,并使命令以确定的用户身份运行,以便任何未来的用户相关活动(例如脚本内的 ACL 检查)都能按预期进行。否则,命令将以 Redis 无限制用户身份运行。从内部连接发送命令时,此标志将被忽略,命令将以 Redis 无限制用户身份运行。 -
S
-- 在脚本模式下运行命令,这意味着如果调用了脚本中不允许的命令(带有deny-script
标志),则会引发错误(例如 SHUTDOWN)。此外,在脚本模式下,如果可用副本不足(如min-replicas-to-write
配置),或者服务器无法持久化到磁盘,则不允许执行写入命令。 -
W
-- 不允许运行任何写入命令(带有write
标志)。 -
M
-- 当超出内存限制时,不允许带有deny-oom
标志的命令。 -
E
-- 将错误作为 RedisModuleCallReply 返回。如果在调用命令之前发生错误,则使用 errno 机制返回错误。此标志还允许将错误作为带有相关错误消息的 error CallReply 获取。 -
'D' -- “空运行”模式。在执行底层 call() 之前返回。如果一切成功,它将返回 NULL,否则将返回表示错误的 CallReply 对象,就像使用 'E' 代码调用一样。
-
'K' -- 允许运行阻塞命令。如果启用此选项且命令被阻塞,将返回一个特殊的 REDISMODULE_REPLY_PROMISE。这种回复类型表明命令已被阻塞,回复将异步给出。模块可以使用此回复对象设置一个处理程序,当命令使用 RedisModule_CallReplyPromiseSetUnblockHandler 解除阻塞时将调用该处理程序。处理程序必须在命令调用后立即设置(期间不能释放 Redis 锁)。如果未设置处理程序,阻塞命令仍将继续执行,但回复将被忽略(一击即忘),注意在角色改变的情况下这是危险的,如下文所述。模块可以使用 RedisModule_CallReplyPromiseAbort 中止尚未完成的命令调用(有关更多详细信息,请参阅 RedisModule_CallReplyPromiseAbort 文档)。在角色改变时中止执行也是模块的责任,可以通过使用服务器事件(在实例成为副本时得到通知)或依赖原始客户端的断开连接回调来实现。未能这样做可能导致在副本上执行写入操作。与其他调用回复不同,promise 调用回复必须在 Redis GIL 锁定时释放。请注意,在解除阻塞时,唯一的保证是 unblock 处理程序将被调用。如果阻塞的 RedisModule_Call 导致模块也阻塞了某个真实客户端(使用 RedisModule_BlockClient),模块有责任在 unblock 处理程序中解除此客户端的阻塞。在 unblock 处理程序中,只允许执行以下操作: * 使用 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: 在 Cluster 实例中,键位于非本地槽位的操作。
- EROFS: 在 Cluster 实例中,当在只读状态下发送写入命令的操作。
- ENETDOWN: 在 Cluster 实例中,当集群宕机的操作。
- 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/docs/latest/develop/reference/modules/
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 Modules 生态系统中必须是唯一的。请发挥创造力... 这样就不会发生冲突。使用 A-Z a-z 9-0 字符集,加上两个 "-_" 字符。一个好主意是使用,例如
<typename>-<vendor>
。例如,“tree-AntZ”可能表示“由 @antirez 实现的树数据结构”。同时使用小写字母和大写字母有助于防止冲突。 -
encver: 编码版本,即模块用于持久化数据的序列化版本。只要“name”匹配,无论使用什么“encver”,RDB 加载都将分派到类型回调函数;但是,模块可以判断它必须加载的编码是否是模块的旧版本。例如,模块“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 从数据库中删除,并且可能很快会被后台线程释放的回调函数指针。请注意,在 FLUSHALL/FLUSHDB(同步和异步)时不会调用此函数,模块可以使用
RedisModuleEvent_FlushDB
钩子来处理这种情况。 -
copy: 用于复制指定键的回调函数指针。模块应执行指定值的深层复制并返回它。此外,还提供了有关源键和目标键名称的提示。NULL 返回值被视为错误,复制操作失败。注意:如果目标键存在并且将被覆盖,将首先调用 copy 回调函数,然后调用 free 回调函数以释放将被替换的值。
-
defrag: 用于请求模块对键进行碎片整理的回调函数指针。然后模块应遍历指针并调用相关的
RedisModule_Defrag*()
函数来整理指针或复杂类型的碎片。只要RedisModule_DefragShouldStop()
返回零值,模块就应该继续遍历;如果完成,则返回零值,如果还有更多工作要做,则返回非零值。如果需要做更多工作,可以使用RedisModule_DefragCursorSet()
和RedisModule_DefragCursorGet()
来跨不同调用跟踪这项工作。通常,碎片整理机制在没有时间限制的情况下调用回调函数,因此RedisModule_DefragShouldStop()
总是返回零。具有时间限制并提供游标支持的“延迟碎片整理”机制仅用于确定具有显著内部复杂性的键。为了确定这一点,碎片整理机制使用free_effort
回调函数和 'active-defrag-max-scan-fields' 配置指令。注意:该值作为void**
传递,如果顶层值指针被碎片整理并因此发生变化,函数应更新该指针。 -
mem_usage2: 类似于
mem_usage
,但提供了RedisModuleKeyOptCtx
参数,以便获取元信息,如键名和数据库 ID,以及用于大小估计的sample_size
(参见 MEMORY USAGE 命令)。 -
free_effort2: 类似于
free_effort
,但提供了RedisModuleKeyOptCtx
参数,以便获取元信息,如键名和数据库 ID。 -
unlink2: 类似于
unlink
,但提供了RedisModuleKeyOptCtx
参数,以便获取元信息,如键名和数据库 ID。 -
copy2: 类似于
copy
,但提供了RedisModuleKeyOptCtx
参数,以便获取元信息,如键名和数据库 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_SetModuleOptions
设置 REDISMODULE_OPTIONS_HANDLE_IO_ERRORS
标志。
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 文件。该值可以是有效数字、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
向 digest 添加一个新元素。对于构成给定数据结构的所有元素,可以一次添加一个元素,多次调用此函数。在添加了所有始终按给定顺序排列的元素后,最终必须调用 RedisModule_DigestEndSequence
。有关更多信息,请参阅 Redis 模块数据类型文档。但是,这是一个使用 Redis 数据类型作为示例的快速示例。
要添加一系列无序元素(例如 Redis Set 的情况),使用的模式是
foreach element {
AddElement(element);
EndSequence();
}
因为 Set 是无序的,所以添加的每个元素的位置不依赖于其他元素。然而,如果我们的元素是成对有序的,例如 Hash 的字段-值对,那么应该使用
foreach key,value {
AddElement(key);
AddElement(value);
EndSequence();
}
因为键和值总是按上述顺序排列,而单个键值对可以在 Redis hash 中的任何位置出现。
有序元素列表将按如下方式实现
foreach element {
AddElement(element);
}
EndSequence();
RedisModule_DigestAddLongLong
void RedisModule_DigestAddLongLong(RedisModuleDigest *md, long long ll);
可用版本 4.0.0
类似于 RedisModule_DigestAddStringBuffer()
,但接受一个 long long
作为输入,在添加到 digest 之前将其转换为字符串。
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 的说明符,而 level 是一个字符串,描述发出日志时使用的日志级别,必须是以下之一:
- “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 命令观察。如果延迟小于配置的 latency-monitor-threshold,则跳过此调用。
从模块阻塞客户端
有关模块中阻塞命令的指南,请参阅 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 回调函数都将被注销。当调用 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,该 API 将触发 auth 回复回调函数(通过 RedisModule_BlockClientOnAuth
提供)。在此回复回调函数中,模块应该认证、拒绝或跳过处理认证。(4) 跳过处理认证 - 返回 REDISMODULE_AUTH_NOT_HANDLED
,但不阻塞客户端。这将允许引擎尝试下一个模块 auth 回调函数。如果所有回调函数都没有认证或拒绝认证,则会尝试基于密码的认证,并将相应地认证或添加失败日志并回复客户端。
注意:如果在阻塞模块认证过程中客户端断开连接,则此 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
命令解除阻塞,这将触发 timeout 回调函数。如果没有注册回调函数,则被阻塞的客户端将被视为未处于阻塞状态,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:如果客户端不能立即得到服务,则会阻塞;稍后当键收到新数据(例如列表 push)时,客户端被解除阻塞并得到服务。
然而,在这种模块 API 的情况下,客户端何时解除阻塞?
- 如果您阻塞在与阻塞操作相关的键类型上(例如列表、有序集合、stream 等),则当相关键被通常会解除该类型原生阻塞操作的操作(例如对列表键执行 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_GetBlockedClientPrivateData
可以从超时回调函数访问在 RedisModule_BlockClientOnKeys()
中提供的 privdata)。
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
订阅通知时,模块必须提供一个事件类型掩码,指示订阅者感兴趣的事件。这可以是以下任何标志的按位或掩码:
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/Replica。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/docs/latest/develop/use/keyspace-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,则向集群中的所有节点发送消息;否则,发送到指定的目标,目标是接收器回调函数或节点迭代函数返回的 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 Cluster 的 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
字符串不以 null 结尾。
报告的标志列表如下:
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 Cluster 标志,以改变 Redis Cluster 的正常行为,特别是为了禁用某些功能。这对于使用 Cluster API 创建不同分布式系统,但仍希望使用 Redis Cluster 消息总线的模块非常有用。可以设置的标志有:
CLUSTER_MODULE_FLAG_NO_FAILOVER
CLUSTER_MODULE_FLAG_NO_REDIRECTION
具有以下效果:
-
NO_FAILOVER
:阻止 Redis Cluster 副本对失效的主节点进行故障转移。同时禁用副本迁移功能。 -
NO_REDIRECTION
:每个节点将接受任何键,而不尝试根据 Redis Cluster 算法进行分区。槽信息仍将在集群中传播,但不起作用。
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 何时被调用很重要:如果它在 'callback' 的开头被调用,意味着事件将每隔 'period' 触发一次。如果它在 'callback' 的末尾被调用,意味着事件之间会有 'period' 毫秒的间隔。(如果执行 'callback' 所花费的时间可以忽略不计,则上述两种说法含义相同)
RedisModule_StopTimer
int RedisModule_StopTimer(RedisModuleCtx *ctx,
RedisModuleTimerID id,
void **data);
可用版本 5.0.0
停止一个定时器,如果找到该定时器、它属于调用模块并且已被停止,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
。如果不是 NULL,则将数据指针设置为创建定时器时 data 参数的值。
RedisModule_GetTimerInfo
int RedisModule_GetTimerInfo(RedisModuleCtx *ctx,
RedisModuleTimerID id,
uint64_t *remaining,
void **data);
可用版本 5.0.0
获取关于定时器的信息:距离触发的剩余时间(毫秒),以及与定时器关联的私有数据指针。如果指定的定时器不存在或属于不同的模块,则不返回信息,函数返回 REDISMODULE_ERR
,否则返回 REDISMODULE_OK
。如果调用者不需要某些信息,arguments remaining 或 data 可以为 NULL。
模块 EventLoop API
RedisModule_EventLoopAdd
int RedisModule_EventLoopAdd(int fd,
int mask,
RedisModuleEventLoopFunc func,
void *user_data);
可用版本 7.0.0
将 pipe / socket 事件添加到事件循环中。
-
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
从事件循环中删除一个 pipe / socket 事件。
-
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
检查命令是否可以根据与用户关联的 ACLs 执行。
成功时返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
并将 errno 设置为以下值:
- ENOENT:指定命令不存在。
- EACCES: 根据 ACL 规则,命令无法执行
RedisModule_ACLCheckKeyPermissions
int RedisModule_ACLCheckKeyPermissions(RedisModuleUser *user,
RedisModuleString *key,
int flags);
可用版本 7.0.0
根据附加到用户的 ACLs 和表示键访问的标志检查用户是否可以访问该键。这些标志与键规范中用于逻辑操作的标志相同。这些标志在 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_ACLCheckKeyPrefixPermissions
int RedisModule_ACLCheckKeyPrefixPermissions(RedisModuleUser *user,
RedisModuleString *prefix,
int flags);
可用版本: 未发布
根据附加到用户的 ACLs 和表示键访问的标志检查用户是否可以访问与给定键前缀匹配的键。这些标志与键规范中用于逻辑操作的标志相同。这些标志在 RedisModule_SetCommandInfo
中记录为 REDISMODULE_CMD_KEY_ACCESS
, REDISMODULE_CMD_KEY_UPDATE
, REDISMODULE_CMD_KEY_INSERT
和 REDISMODULE_CMD_KEY_DELETE
标志。
如果未提供任何标志,该命令要成功返回,用户仍然需要对与该前缀匹配的键具有某种访问权限。
如果用户能够访问与该前缀匹配的键,则返回 REDISMODULE_OK
。否则,返回 REDISMODULE_ERR
并将 errno 设置为以下值之一:
- EINVAL:提供的标志无效。
- EACCES:用户没有权限访问与该前缀匹配的键。
RedisModule_ACLCheckChannelPermissions
int RedisModule_ACLCheckChannelPermissions(RedisModuleUser *user,
RedisModuleString *ch,
int flags);
可用版本 7.0.0
根据给定的访问标志检查用户是否可以访问 pubsub 通道。有关可以传递的可能标志的更多信息,请参阅 RedisModule_ChannelAtPosWithFlags
。
如果用户能够访问 pubsub 通道,则返回 REDISMODULE_OK
,否则返回 REDISMODULE_ERR
并将 errno 设置为以下值之一:
- EINVAL:提供的标志无效。
- EACCESS:用户没有权限访问 pubsub 通道。
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
。
有关 authenticateClientWithUser 的回调、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
。
有关 authenticateClientWithUser 的回调、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' 从指定键开始迭代,'op' 只是一个字符串,指定用于查找第一个元素的比较操作符。可用的操作符有:
^
– 查找第一个(字典序较小)键。$
– 查找最后一个(字典序较大)键。>
– 查找第一个大于指定键的元素。>=
– 查找第一个大于或等于指定键的元素。<
– 查找小于指定键的第一个元素。<=
– 查找小于或等于指定键的第一个元素。==
– 精确查找与指定键匹配的第一个元素。
请注意,对于 ^
和 $
操作符,传入的键不被使用,用户可以只传递 NULL 和长度 0。
如果根据传入的键和操作符无法查找迭代的起始元素,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
使用 RedisModule_DictIteratorStart()
创建迭代器后,可以使用此 API 调用更改迭代器当前选定的元素。基于操作符和键的结果与函数 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*
,有时强制转换为 unsigned 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' 中分配的模块字符串对象(该上下文可以为 NULL,就像主要 API RedisModule_CreateString
一样)。
返回的字符串对象在使用后应被释放,可以手动释放,也可以使用启用了自动内存管理的上下文。
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' 将迭代器当前指向的元素与由 key/keylen 给定的指定元素进行比较(有效操作符集合与 RedisModule_DictIteratorStart
有效的操作符相同)。如果比较成功,命令返回 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
用于在添加任何字段之前开始一个新 section。section 名称将以 <modulename>_
为前缀,且只能包含 A-Z、a-z、0-9。NULL 或空字符串表示使用默认 section(仅 <modulename>
)。当返回值为 REDISMODULE_ERR
时,该 section 应该且将被跳过。
RedisModule_InfoBeginDictField
int RedisModule_InfoBeginDictField(RedisModuleInfoCtx *ctx, const char *name);
可用版本 6.0.0
开始一个 dict 字段,类似于 INFO KEYSPACE 中的字段。使用常规的 RedisModule_InfoAddField
* 函数向此字段添加项,并使用 RedisModule_InfoEndDictField
结束。
RedisModule_InfoEndDictField
int RedisModule_InfoEndDictField(RedisModuleInfoCtx *ctx);
可用版本 6.0.0
结束一个 dict 字段,参见 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()
创建的数据。只有当字典是使用上下文创建而非传入 NULL 时,才需要传递上下文指针 'ctx'。
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*,调用者不应释放此指针。
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()
收集的数据中获取字段的值。如果未找到该字段,或者该字段不是 double 类型,返回值将为 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()
调用。 - 从主节点复制命令。
过滤器在一个特殊的过滤上下文(filter context)中执行,该上下文与 RedisModuleCtx
不同且限制更多。因为过滤器影响任何命令,所以必须以非常高效的方式实现,以减少对 Redis 性能的影响。所有需要有效上下文的 Redis 模块 API 调用(例如 RedisModule_Call()
、RedisModule_OpenKey()
等)在过滤上下文中不受支持。
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,允许模块扫描所选数据库中的所有键和值。
扫描实现的 callback。
void scan_callback(RedisModuleCtx *ctx, RedisModuleString *keyname,
RedisModuleKey *key, void *privdata);
ctx
:为扫描提供的 redis 模块上下文。keyname
:归调用者所有,如果在此函数后使用,需要保留。key
:包含键和值的信息,尽力提供,在某些情况下可能为 NULL,此时用户应该(可以)使用RedisModule_OpenKey()
(以及 CloseKey)。提供时,它归调用者所有,并在 callback 返回时释放。privdata
:提供给RedisModule_Scan()
的用户数据。
使用方法
RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
while(RedisModule_Scan(ctx, c, callback, privateData));
RedisModule_ScanCursorDestroy(c);
在实际调用 RedisModule_Scan
期间获取锁时,也可以在另一个线程中使用此 API。
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,允许模块扫描 hash、set 或 sorted set 键中的元素。
扫描实现的 callback。
void scan_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata);
- key - 为扫描提供的 redis 键上下文。
- field - 字段名,归调用者所有,如果在此函数后使用,需要保留。
- value - 值字符串,对于 set 类型可能为 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);
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
。当子进程退出时(但不包括被杀死时),将在父进程上执行完成处理程序回调。返回值:失败时返回 -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 将提供给在父进程上执行的完成处理程序。
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
注册在指定服务器事件发生时通过 callback 通知。callback 调用时将事件作为参数,还有一个额外的参数是一个 void 指针,应根据事件特定类型进行强制转换(但许多事件将只使用 NULL,因为它们没有额外信息传递给 callback)。
如果 callback 为 NULL 且之前有订阅,则模块将被取消订阅。如果之前有订阅且 callback 不为 NULL,则旧 callback 将被新 callback 替换。
callback 必须是这种类型
int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,
RedisModuleEvent eid,
uint64_t subevent,
void *data);
'ctx' 是一个正常的 Redis 模块上下文,callback 可以使用它来调用其他模块 API。'eid' 是事件本身,这只在模块订阅了多个事件的情况下有用:使用此结构的 'id' 字段可以检查事件是否是我们使用此 callback 注册的事件之一。'subevent' 字段取决于触发的事件。
最后,仅针对某些事件,'data' 指针可能填充了更多相关数据。
这是您可以作为 'eid' 使用的事件列表以及相关的 sub event:
-
RedisModuleEvent_ReplicationRoleChanged
:当实例从 master 切换到 replica 或反向切换时会调用此事件,但当 replica 仍然是 replica 但开始与不同的 master 复制时也会调用此事件。
提供以下 sub event:
REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_MASTER
REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA
callback 可以将 '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 重写开始和结束时会调用此事件。提供以下 sub event:
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 sub event 由于 SAVE 命令、FLUSHALL 或服务器关机而在前台发生,其他 RDB 和 AOF sub event 在后台 fork 的子进程中执行,因此模块采取的任何操作只能影响生成的 AOF 或 RDB,而不会反映在父进程中并影响连接的客户端和命令。另请注意,在带有 rdb-preamble 的 AOF 情况下,AOF_START sub event 最终可能会保存 RDB 内容。
-
RedisModuleEvent_FlushDB
FLUSHALL、FLUSHDB 或内部 flush(例如由于复制,在 replica 同步之后)发生。提供以下 sub event:
REDISMODULE_SUBEVENT_FLUSHDB_START
REDISMODULE_SUBEVENT_FLUSHDB_END
data 指针可以强制转换为包含以下字段的 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.
start 事件在操作启动 之前 调用,因此允许 callback 对尚未释放的键空间调用 DBSIZE 或其他操作。
-
RedisModuleEvent_Loading
在加载操作时调用:服务器启动时的启动阶段,以及 replica 从 master 加载 RDB 文件后的首次同步阶段。提供以下 sub event:
REDISMODULE_SUBEVENT_LOADING_RDB_START
REDISMODULE_SUBEVENT_LOADING_AOF_START
REDISMODULE_SUBEVENT_LOADING_REPL_START
REDISMODULE_SUBEVENT_LOADING_ENDED
REDISMODULE_SUBEVENT_LOADING_FAILED
请注意,在带有 rdb-preamble 的情况下,AOF 加载可能会从 RDB 数据开始,此时您将只收到一个 AOF_START 事件。
-
RedisModuleEvent_ClientChange
当客户端连接或断开连接时调用。data 指针可以强制转换为 RedisModuleClientInfo 结构体,该结构体在 RedisModule_GetClientInfoById() 中有文档说明。提供以下 sub event:
REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED
-
RedisModuleEvent_Shutdown
服务器正在关闭。没有可用的 sub event。
-
RedisModuleEvent_ReplicaChange
当实例(可以是 master 或 replica)获得新的在线 replica,或者因为 replica 断开连接而失去 replica 时会调用此事件。提供以下 sub event:
REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE
REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE
目前没有其他附加信息:Redis 的未来版本将提供 API 以枚举连接的 replica 及其状态。
-
RedisModuleEvent_CronLoop
每当 Redis 调用 serverCron() 函数进行某些簿记操作时,都会调用此事件。需要不时执行操作的模块可以使用此 callback。通常 Redis 每秒调用此函数 10 次,但这会根据 "hz" 配置而变化。没有可用的 sub event。
data 指针可以强制转换为包含以下字段的 RedisModuleCronLoop 结构体:
int32_t hz; // Approximate number of events per second.
-
RedisModuleEvent_MasterLinkChange
对于 replicas 调用此函数,以通知与 master 的复制链接何时变为可用(up)或断开(down)。请注意,只有当复制正常进行时才认为链接已连接,而不仅仅是连接到 master 时。提供以下 sub event:
REDISMODULE_SUBEVENT_MASTER_LINK_UP
REDISMODULE_SUBEVENT_MASTER_LINK_DOWN
-
RedisModuleEvent_ModuleChange
当加载新模块或卸载模块时调用此事件。提供以下 sub event:
REDISMODULE_SUBEVENT_MODULE_LOADED
REDISMODULE_SUBEVENT_MODULE_UNLOADED
data 指针可以强制转换为包含以下字段的 RedisModuleModuleChange 结构体:
const char* module_name; // Name of module loaded or unloaded. int32_t module_version; // Module version.
-
RedisModuleEvent_LoadingProgress
在加载 RDB 或 AOF 文件时反复调用此事件。提供以下 sub event:
REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB
REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF
data 指针可以强制转换为包含以下字段的 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 命令时调用此事件。目前对于此事件调用没有可用的 sub event。
data 指针可以强制转换为包含以下字段的 RedisModuleSwapDbInfo 结构体:
int32_t dbnum_first; // Swap Db first dbnum int32_t dbnum_second; // Swap Db second dbnum
-
RedisModuleEvent_ReplBackup
警告:从 Redis 7.0 开始,复制备份事件(Replication Backup events)已被弃用,并且不会被触发。请参阅 RedisModuleEvent_ReplAsyncLoad 以了解当 repl-diskless-load 设置为 swapdb 时如何触发异步复制加载事件(Async Replication Loading events)。
当 repl-diskless-load 配置设置为 swapdb 时调用,并且 Redis 需要备份当前数据库以备将来恢复。具有全局数据以及可能带有 aux_load 和 aux_save callback 的模块可能需要使用此通知来备份/恢复/丢弃其全局数据。提供以下 sub event:
REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE
REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE
REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD
-
RedisModuleEvent_ReplAsyncLoad
当 repl-diskless-load 配置设置为 swapdb 且发生与具有相同数据集历史(匹配复制 ID)的 master 进行复制时调用。在这种情况下,Redis 在从 socket 将新数据库加载到内存中时,提供当前数据集服务。模块必须声明支持此机制(通过 REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD 标志)才能激活它。提供以下 sub event:
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED
REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED
-
RedisModuleEvent_ForkChild
当 fork 的子进程(AOFRW、RDBSAVE、模块 fork 等)诞生/死亡时调用。提供以下 sub event:
REDISMODULE_SUBEVENT_FORK_CHILD_BORN
REDISMODULE_SUBEVENT_FORK_CHILD_DIED
-
RedisModuleEvent_EventLoop
在每次事件循环迭代时调用,一次是在事件循环进入休眠之前,另一次是在事件循环唤醒之后。提供以下 sub event:
REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP
REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP
-
RedisModule_Event_Config
当配置事件发生时调用。提供以下 sub event:
REDISMODULE_SUBEVENT_CONFIG_CHANGE
data 指针可以强制转换为包含以下字段的 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
当键从键空间中移除时调用。在此事件中我们不能修改任何键。提供以下 sub event:
REDISMODULE_SUBEVENT_KEY_DELETED
REDISMODULE_SUBEVENT_KEY_EXPIRED
REDISMODULE_SUBEVENT_KEY_EVICTED
REDISMODULE_SUBEVENT_KEY_OVERWRITTEN
data 指针可以强制转换为包含以下字段的 RedisModuleKeyInfo 结构体:
RedisModuleKey *key; // Key name
如果模块成功订阅了指定的事件,函数返回 REDISMODULE_OK
。如果从错误的上下文调用 API 或给定了不支持的事件,则返回 REDISMODULE_ERR
。
RedisModule_IsSubEventSupported
int RedisModule_IsSubEventSupported(RedisModuleEvent event, int64_t subevent);
可用版本 6.0.9
对于给定的服务器事件和 sub event,如果 sub event 不受支持则返回零,否则返回非零。
模块配置 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
callback 来访问或操作该值。getfn
callback 从模块中检索值,而 setfn
callback 提供要存储到模块配置中的值。可选的 applyfn
callback 在 CONFIG SET
命令使用 setfn
callback 修改一个或多个配置后调用,可用于在多个配置一起更改后原子地应用配置。如果单个 CONFIG SET
命令设置了多个带有 applyfn
callback 的配置,如果它们的 applyfn
函数和 privdata
指针相同,它们将被去重,并且 callback 只运行一次。如果提供的值无效或无法使用,setfn
和 applyfn
都可以返回错误。配置还声明了由 Redis 验证并提供给模块的值的类型。配置系统提供以下类型:
- Redis 字符串:二进制安全的字符串数据。
- 枚举:有限数量的字符串 token 之一,在注册期间提供。
- 数字:64 位带符号整数,也支持最小值和最大值。
- 布尔值:是或否的值。
当值成功应用时,setfn
callback 预期返回 REDISMODULE_OK
。如果无法应用该值,它也可以返回 REDISMODULE_ERR
,并且可以使用 RedisModuleString
错误消息设置 *err 指针以提供给客户端。此 RedisModuleString
在从 set callback 返回后将由 redis 释放。
所有配置都使用名称、类型、默认值、在 callback 中可用的私有数据以及修改配置行为的几个标志进行注册。名称只能包含字母数字字符或破折号。支持的标志有:
REDISMODULE_CONFIG_DEFAULT
:配置的默认标志。这将创建一个启动后可修改的配置。REDISMODULE_CONFIG_IMMUTABLE
:此配置只能在加载时提供。REDISMODULE_CONFIG_SENSITIVE
:此配置中存储的值将从所有日志中 redacted(删除敏感信息)。REDISMODULE_CONFIG_HIDDEN
:使用模式匹配时,名称对CONFIG GET
隐藏。REDISMODULE_CONFIG_PROTECTED
:此配置只能根据 enable-protected-configs 的值进行修改。REDISMODULE_CONFIG_DENY_LOADING
:服务器加载数据期间,此配置不可修改。REDISMODULE_CONFIG_MEMORY
:对于数字配置,此配置将数据单位符号转换为其字节等效值。REDISMODULE_CONFIG_BITFLAGS
:对于枚举配置,此配置将允许将多个条目组合为位标志。
如果通过配置文件或命令行未提供值,默认值将在启动时用于设置值。默认值也用于在配置重写时进行比较。
注意
- 在字符串配置设置中,传递给 set callback 的字符串将在执行后释放,模块必须保留它。
- 在字符串配置获取中,字符串不会被消耗,并在执行后仍然有效。
示例实现
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
命令与其交互。枚举配置是一组字符串 token 到对应的整数值,其中字符串值暴露给 Redis 客户端,但传递给 Redis 和模块的值是整数值。这些值在 enum_values
(以 null 结尾的 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_LoadDefaultConfigs
int RedisModule_LoadDefaultConfigs(RedisModuleCtx *ctx);
可用版本: 未发布
应用模块注册的所有参数的默认配置。只有当模块希望在实际值通过 RedisModule_LoadConfigs
应用之前更改配置值时,才调用此函数。否则,只需调用 RedisModule_LoadConfigs
,它应该在需要时已经设置了默认值。这使得区分默认值和用户提供的值成为可能,并在设置默认值和用户值之间应用其他更改。如果在以下情况调用此函数,将返回 REDISMODULE_ERR
:
- 在
RedisModule_OnLoad
外部 - 多次调用
- 在
RedisModule_LoadConfigs
调用之后
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);
RedisModule_GetInternalSecret
const char* RedisModule_GetInternalSecret(RedisModuleCtx *ctx, size_t *len);
可用版本: 未发布
返回集群的内部密钥。应使用此密钥作为内部连接对集群中的节点进行身份验证,从而获得执行内部命令的权限。
键逐出 API
RedisModule_SetLRU
int RedisModule_SetLRU(RedisModuleKey *key, mstime_t lru_idle);
可用版本 6.0.0
设置键的最后访问时间,用于基于 LRU 的驱逐。如果服务器的最大内存策略是基于 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
设置键的访问频率。仅当服务器的最大内存策略是基于 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
返回 Redis 版本,格式为 0x00MMmmpp。例如,对于 6.0.7,返回值为 0x00060007。
RedisModule_GetTypeMethodVersion
int RedisModule_GetTypeMethodVersion(void);
可用版本 6.2.0
返回 REDISMODULE_TYPE_METHOD_VERSION
当前的 Redis 服务器运行时值。调用 RedisModule_CreateDataType
时可以使用此值来了解 RedisModuleTypeMethods
的哪些字段将被支持,哪些将被忽略。
RedisModule_ModuleTypeReplaceValue
int RedisModule_ModuleTypeReplaceValue(RedisModuleKey *key,
moduleType *mt,
void *new_value,
void **old_value);
可用版本 6.0.0
替换分配给模块类型的值。
键必须以写模式打开,具有现有值,并且其模块类型必须与调用者指定的类型匹配。
与将释放旧值的 RedisModule_ModuleTypeSetValue()
不同,此函数仅用新值交换旧值。
成功时函数返回 REDISMODULE_OK
,出现错误时返回 REDISMODULE_ERR
,例如:
- 键未以写模式打开。
- 键不是模块数据类型键。
- 键是模块数据类型,但不是 'mt'。
如果 old_value
非 NULL,则通过引用返回旧值。
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_RegisterDefragFunc2
int RedisModule_RegisterDefragFunc2(RedisModuleCtx *ctx,
RedisModuleDefragFunc2 cb);
可用版本: 未发布
为全局数据注册碎片整理回调,即模块可能分配的任何不绑定到特定数据类型的数据。这是 RedisModule_RegisterDefragFunc
的更高级版本,因为它接受一个带返回值的回调,并且可以使用 RedisModule_DefragShouldStop
来指示它应该稍后再次调用,还是已完成(返回 0)。
RedisModule_RegisterDefragCallbacks
int RedisModule_RegisterDefragCallbacks(RedisModuleCtx *ctx,
RedisModuleDefragFunc start,
RedisModuleDefragFunc end);
可用版本: 未发布
注册碎片整理回调,这些回调将在碎片整理操作开始和结束时调用。
回调与 RedisModule_RegisterDefragFunc
相同,但用户也可以假设这些回调在碎片整理操作开始和结束时被调用。
RedisModule_DefragShouldStop
int RedisModule_DefragShouldStop(RedisModuleDefragCtx *ctx);
可用版本 6.2.0
当数据类型碎片整理回调遍历复杂结构时,应定期调用此函数。返回零(假)表示回调可以继续其工作。非零值(真)表示应停止。
停止时,回调可以使用 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_DefragAllocRaw
void *RedisModule_DefragAllocRaw(RedisModuleDefragCtx *ctx, size_t size);
可用版本: 未发布
为碎片整理目的分配内存
在常见情况下,用户只需重新分配具有单个所有者的指针。对于这种情况,RedisModule_DefragAlloc
就足够了。但在某些用例中,用户可能希望替换不同键中具有多个所有者的指针。在这种情况下,原地替换无法工作,因为其他键仍然保留指向旧值的指针。
RedisModule_DefragAllocRaw
和 RedisModule_DefragFreeRaw
允许控制何时为碎片整理目的分配内存以及何时释放内存,从而支持更复杂的碎片整理用例。
RedisModule_DefragFreeRaw
void RedisModule_DefragFreeRaw(RedisModuleDefragCtx *ctx, void *ptr);
可用版本: 未发布
为碎片整理目的释放内存
有关更多信息,请参阅 RedisModule_DefragAllocRaw
。
RedisModule_DefragRedisModuleString
RedisModuleString *RedisModule_DefragRedisModuleString(RedisModuleDefragCtx *ctx,
RedisModuleString *str);
可用版本 6.2.0
对先前使用 RedisModule_Alloc
、RedisModule_Calloc
等分配的 RedisModuleString
进行碎片整理。有关碎片整理过程如何工作的更多信息,请参阅 RedisModule_DefragAlloc()
。
注意:只能对具有单个引用的字符串进行碎片整理。通常这意味着使用 RedisModule_RetainString
或 RedisModule_HoldString
保留的字符串可能无法进行碎片整理。一个例外是命令参数,如果由模块保留,它们将最终具有单个引用(因为命令回调返回后,Redis 端的引用被丢弃)。
RedisModule_DefragRedisModuleDict
RedisModuleDict *RedisModule_DefragRedisModuleDict(RedisModuleDefragCtx *ctx,
RedisModuleDict *dict,
RedisModuleDefragDictValueCallback valueCB,
RedisModuleString **seekTo);
可用版本: 未发布
通过扫描其内容并为每个值调用值回调函数来对 Redis 模块字典进行碎片整理。
回调函数获取字典中的当前值,如果值被重新分配到不同的地址,则应将 newptr 更新为新指针。回调函数还获取键名作为参考。当此节点的碎片整理完成时,回调函数返回 0;当节点需要更多工作时,返回 1。
此 API 可以增量工作,它接受一个寻求位置以从中继续,并在下次调用时返回要寻求到的下一个位置(或者当迭代完成时返回 NULL)。
如果字典被重新分配到新地址,此 API 返回一个新的字典(仅当入口时 *seekTo 为 NULL 时才会尝试)。
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_ACLCheckKeyPrefixPermissions
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_DefragAllocRaw
RedisModule_DefragCursorGet
RedisModule_DefragCursorSet
RedisModule_DefragFreeRaw
RedisModule_DefragRedisModuleDict
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_GetInternalSecret
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_HashFieldMinExpire
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_LoadDefaultConfigs
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_RegisterDefragCallbacks
RedisModule_RegisterDefragFunc
RedisModule_RegisterDefragFunc2
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