章节
- 堆分配原始函数
- 命令 API
- 模块信息和时间测量
- 模块自动内存管理
- 字符串对象 API
- 回复 API
- 命令复制 API
- DB 和 Key API – 通用 API
- 字符串类型 Key API
- 列表类型 Key API
- 有序集合类型 Key API
- 有序集合迭代器 Key API
- 哈希类型 Key API
- 流类型 Key API
- 从模块调用命令
- 模块数据类型
- RDB 加载和保存函数
- Key Digest API(用于模块类型的 DEBUG DIGEST 接口)
- 用于模块数据类型的 AOF API
- IO 上下文处理
- 日志记录
- 从模块阻塞客户端
- 线程安全上下文
- 模块键空间通知 API
- 模块集群 API
- 模块计时器 API
- 模块事件循环 API
- 模块 ACL API
- 模块字典 API
- 模块信息字段
- 模块实用工具 API
- 模块 API 导出/导入
- 模块命令过滤器 API
- 扫描键空间和哈希
- 模块 fork API
- 服务器钩子实现
- 模块配置 API
- RDB 加载/保存 API
- Key 淘汰 API
- 杂项 API
- 碎片整理 API
- 函数索引
堆分配原始函数
使用这些函数分配的内存会被 Key 淘汰算法考虑在内,并报告在内存使用信息中。
ValkeyModule_Alloc
void *ValkeyModule_Alloc(size_t bytes);
可用版本 4.0.0
用法类似 malloc()
。使用此函数分配的内存会在 INFO memory 中报告,根据 maxmemory 设置用于 Key 淘汰,并且通常被视为服务器分配的内存。您应该避免直接使用 malloc()
。如果无法分配足够的内存,此函数将导致程序崩溃。
ValkeyModule_TryAlloc
void *ValkeyModule_TryAlloc(size_t bytes);
可用版本 7.0.0
类似于 ValkeyModule_Alloc
,但如果分配失败,则返回 NULL,而不是导致程序崩溃。
ValkeyModule_Calloc
void *ValkeyModule_Calloc(size_t nmemb, size_t size);
可用版本 4.0.0
用法类似 calloc()
。使用此函数分配的内存会在 INFO memory 中报告,根据 maxmemory 设置用于 Key 淘汰,并且通常被视为服务器分配的内存。您应该避免直接使用 calloc()
。
ValkeyModule_TryCalloc
void *ValkeyModule_TryCalloc(size_t nmemb, size_t size);
可用版本 8.0.0
类似于 ValkeyModule_Calloc
,但如果分配失败,则返回 NULL,而不是导致程序崩溃。
ValkeyModule_Realloc
void *ValkeyModule_Realloc(void *ptr, size_t bytes);
可用版本 4.0.0
用法类似 realloc()
,用于通过 ValkeyModule_Alloc()
获取的内存。
ValkeyModule_TryRealloc
void *ValkeyModule_TryRealloc(void *ptr, size_t bytes);
可用版本 8.0.0
类似于 ValkeyModule_Realloc
,但如果分配失败,则返回 NULL,而不是导致程序崩溃。
ValkeyModule_Free
void ValkeyModule_Free(void *ptr);
可用版本 4.0.0
用法类似 free()
,用于通过 ValkeyModule_Alloc()
和 ValkeyModule_Realloc()
获取的内存。但是,您绝不应尝试使用 ValkeyModule_Free()
释放模块内部通过 malloc()
分配的内存。
ValkeyModule_Strdup
char *ValkeyModule_Strdup(const char *str);
可用版本 4.0.0
类似于 strdup()
,但返回使用 ValkeyModule_Alloc()
分配的内存。
ValkeyModule_PoolAlloc
void *ValkeyModule_PoolAlloc(ValkeyModuleCtx *ctx, size_t bytes);
可用版本 4.0.0
返回堆分配的内存,该内存将在模块回调函数返回时自动释放。主要适用于短生命周期的小型分配,无论如何都必须在回调返回时释放。如果请求的字节数至少为字长,则返回的内存会按架构字长对齐;否则,它仅对齐到下一个2的幂,例如,3字节请求会4字节对齐,而2字节请求会2字节对齐。
没有 realloc
风格的函数,因为在这种情况下使用内存池分配器并不是一个好主意。
如果 bytes
为 0,函数返回 NULL。
命令 API
这些函数用于实现自定义命令。
示例请参见 https://valkey.com.cn/topics/modules-intro。
ValkeyModule_IsKeysPositionRequest
int ValkeyModule_IsKeysPositionRequest(ValkeyModuleCtx *ctx);
可用版本 4.0.0
如果一个使用“getkeys-api”标志声明的模块命令以特殊方式被调用以获取键位置而不是执行,则返回非零值。否则返回零。
ValkeyModule_KeyAtPosWithFlags
void ValkeyModule_KeyAtPosWithFlags(ValkeyModuleCtx *ctx, int pos, int flags);
可用版本 7.0.0
当一个模块命令被调用以获取键的位置时(因为它在注册期间被标记为“getkeys-api”),命令实现会使用 ValkeyModule_IsKeysPositionRequest()
API 检查此特殊调用,并使用此函数报告键。
支持的标志与 ValkeyModule_SetCommandInfo
使用的标志相同,请参见 VALKEYMODULE_CMD_KEY_
*。
以下是其用法示例:
if (ValkeyModule_IsKeysPositionRequest(ctx)) {
ValkeyModule_KeyAtPosWithFlags(ctx, 2, VALKEYMODULE_CMD_KEY_RO | VALKEYMODULE_CMD_KEY_ACCESS);
ValkeyModule_KeyAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_KEY_RW | VALKEYMODULE_CMD_KEY_UPDATE |
VALKEYMODULE_CMD_KEY_ACCESS
);
}
注意:在上面的示例中,get keys API 可以通过 key-specs 处理(推荐)。只有当无法声明覆盖所有键的 key-specs 时,才需要实现 getkeys-api。
ValkeyModule_KeyAtPos
void ValkeyModule_KeyAtPos(ValkeyModuleCtx *ctx, int pos);
可用版本 4.0.0
此 API 存在于 ValkeyModule_KeyAtPosWithFlags
添加之前,现已弃用,可用于与旧版本(在引入 key-specs 和 flags 之前)的兼容。
ValkeyModule_IsChannelsPositionRequest
int ValkeyModule_IsChannelsPositionRequest(ValkeyModuleCtx *ctx);
可用版本 7.0.0
如果一个用“getchannels-api”标志声明的模块命令以特殊方式被调用以获取通道位置而不是执行,则返回非零值。否则返回零。
ValkeyModule_ChannelAtPosWithFlags
void ValkeyModule_ChannelAtPosWithFlags(ValkeyModuleCtx *ctx,
int pos,
int flags);
可用版本 7.0.0
当一个模块命令被调用以获取通道的位置时(因为它在注册期间被标记为“getchannels-api”),命令实现会使用 ValkeyModule_IsChannelsPositionRequest()
API 检查此特殊调用,并使用此函数报告通道。
支持的标志是
VALKEYMODULE_CMD_CHANNEL_SUBSCRIBE
:此命令将订阅该通道。VALKEYMODULE_CMD_CHANNEL_UNSUBSCRIBE
:此命令将取消订阅该通道。VALKEYMODULE_CMD_CHANNEL_PUBLISH
:此命令将发布到该通道。VALKEYMODULE_CMD_CHANNEL_PATTERN
:不作用于特定通道,而是作用于模式指定的任何通道。这与 PSUBSCRIBE 和 PUNSUBSCRIBE 命令使用的访问方式相同。不打算与 PUBLISH 权限一起使用。
以下是其用法示例:
if (ValkeyModule_IsChannelsPositionRequest(ctx)) {
ValkeyModule_ChannelAtPosWithFlags(ctx, 1, VALKEYMODULE_CMD_CHANNEL_SUBSCRIBE | VALKEYMODULE_CMD_CHANNEL_PATTERN);
ValkeyModule_ChannelAtPosWithFlags(ctx, 1, `VALKEYMODULE_CMD_CHANNEL_PUBLISH`);
}
注意:声明通道的一个用途是评估 ACL 权限。在这种情况下,取消订阅总是允许的,因此命令只会被检查订阅和发布权限。这比使用 ValkeyModule_ACLCheckChannelPermissions
更受推荐,因为它允许在命令执行之前检查 ACL。
ValkeyModule_CreateCommand
int ValkeyModule_CreateCommand(ValkeyModuleCtx *ctx,
const char *name,
ValkeyModuleCmdFunc cmdfunc,
const char *strflags,
int firstkey,
int lastkey,
int keystep);
可用版本 4.0.0
在服务器中注册一个新命令,该命令将使用 ValkeyModule 调用约定通过调用函数指针 'cmdfunc' 来处理。
函数在以下情况下返回 VALKEYMODULE_ERR
- 在
ValkeyModule_OnLoad
之外调用模块命令创建。 - 指定的命令已占用。
- 命令名称包含一些不允许的字符。
- 传递了一组无效标志。
否则返回 VALKEYMODULE_OK
并注册新命令。
此函数必须在模块初始化期间在 ValkeyModule_OnLoad()
函数内部调用。在初始化函数之外调用此函数是未定义的。
命令函数类型如下:
int MyCommand_ValkeyCommand(ValkeyModuleCtx *ctx, ValkeyModuleString **argv, int argc);
并且应始终返回 VALKEYMODULE_OK
。
标志集 'strflags' 指定了命令的行为,应作为由空格分隔的单词组成的 C 字符串传递,例如 "write deny-oom"。标志集有:
- "write":命令可能修改数据集(也可能从中读取)。
- "readonly":命令从键返回数据,但从不写入。
- "admin":命令是管理命令(可能更改复制或执行类似任务)。
- "deny-oom":命令可能使用额外内存,应在内存不足情况下被拒绝。
- "deny-script":不允许在 Lua 脚本中使用此命令。
- "allow-loading":允许服务器加载数据时运行此命令。只有不与数据集交互的命令才应允许在此模式下运行。如果不确定,请勿使用此标志。
- "pubsub":命令在 Pub/Sub 通道上发布内容。
- "random":即使输入参数和键值相同,命令也可能产生不同的输出。从 Redis OSS 7.0 开始,此标志已被弃用。将命令声明为“random”可以通过命令提示来完成,请参阅 https://valkey.com.cn/topics/command-tips。
- "allow-stale":允许该命令在不提供陈旧数据的副本上运行。如果您不了解其含义,请勿使用。
- "no-monitor":不要在 monitor 上传播该命令。如果命令的参数中包含敏感数据,请使用此选项。
- "no-slowlog":已弃用,请使用 "no-commandlog"。
- "no-commandlog":不要将此命令记录到 commandlog 中。如果命令的参数中包含敏感数据,请使用此选项。
- "fast":命令的时间复杂度不大于 O(log(N)),其中 N 是集合的大小或任何其他表示命令正常可伸缩性问题的值。
- "getkeys-api":命令实现了返回作为键的参数的接口。当 start/stop/step 因命令语法不足时使用。
- "no-cluster":命令不应在集群中注册,因为它未设计为与集群配合使用,例如,无法报告键的位置、以编程方式创建键名或任何其他原因。
- "no-auth":此命令可由未经身份验证的客户端运行。通常这用于对客户端进行身份验证的命令。
- "may-replicate":此命令可能会生成复制流量,即使它不是写入命令。
- "no-mandatory-keys":此命令可能接受的所有键都是可选的
- "blocking":该命令有可能阻塞客户端。
- "allow-busy":允许服务器被脚本或慢速模块命令阻塞时执行该命令,请参阅 ValkeyModule_Yield。
- "getchannels-api":命令实现了返回作为通道的参数的接口。
最后三个参数指定新命令的哪些参数是键。有关更多信息,请参阅 https://valkey.com.cn/commands/command。
firstkey
:第一个键参数的基于1的索引。位置0始终是命令名称本身。没有键的命令为0。lastkey
:最后一个键参数的基于1的索引。负数表示从最后一个参数向后计数(-1表示提供的最后一个参数),没有键的命令为0。keystep
:第一个和最后一个键索引之间的步长。没有键的命令为0。
此信息由 ACL、Cluster 和 COMMAND
命令使用。
注意:上述方案用途有限,只能用于查找存在于常量索引处的键。对于非平凡的键参数,您可以传递 0,0,0 并使用 ValkeyModule_SetCommandInfo
通过更高级的方案设置键规范,并使用 ValkeyModule_SetCommandACLCategories
设置命令的 ACL 类别。
ValkeyModule_GetCommand
ValkeyModuleCommand *ValkeyModule_GetCommand(ValkeyModuleCtx *ctx,
const char *name);
可用版本 7.0.0
通过命令名称获取一个不透明结构,表示一个模块命令。此结构用于一些与命令相关的 API。
在以下错误情况下返回 NULL
- 命令未找到
- 该命令不是模块命令
- 该命令不属于调用模块
ValkeyModule_CreateSubcommand
int ValkeyModule_CreateSubcommand(ValkeyModuleCommand *parent,
const char *name,
ValkeyModuleCmdFunc cmdfunc,
const char *strflags,
int firstkey,
int lastkey,
int keystep);
可用版本 7.0.0
与 ValkeyModule_CreateCommand
非常相似,但用于创建与另一个容器命令关联的子命令。
示例:如果一个模块有一个配置命令,MODULE.CONFIG,那么 GET 和 SET 应该是个别子命令,而 MODULE.CONFIG 是一个命令,但不应注册有效的 funcptr
if (ValkeyModule_CreateCommand(ctx,"module.config",NULL,"",0,0,0) == VALKEYMODULE_ERR)
return VALKEYMODULE_ERR;
ValkeyModuleCommand *parent = ValkeyModule_GetCommand(ctx,,"module.config");
if (ValkeyModule_CreateSubcommand(parent,"set",cmd_config_set,"",0,0,0) == VALKEYMODULE_ERR)
return VALKEYMODULE_ERR;
if (ValkeyModule_CreateSubcommand(parent,"get",cmd_config_get,"",0,0,0) == VALKEYMODULE_ERR)
return VALKEYMODULE_ERR;
成功时返回 VALKEYMODULE_OK
,在以下错误情况下返回 VALKEYMODULE_ERR
- 解析
strflags
时出错 - 命令被标记为
no-cluster
但集群模式已启用 parent
已经是一个子命令(我们不允许超过一级命令嵌套)parent
是一个带有实现的命令(ValkeyModuleCmdFunc
)(父命令应该是一个纯粹的子命令容器)parent
已经有一个名为name
的子命令- 在
ValkeyModule_OnLoad
之外调用创建子命令。
ValkeyModule_AddACLCategory
int ValkeyModule_AddACLCategory(ValkeyModuleCtx *ctx, const char *name);
可用版本 8.0.0
ValkeyModule_AddACLCategory
可用于添加新的 ACL 命令类别。类别名称只能包含字母数字字符、下划线或连字符。类别只能在 ValkeyModule_OnLoad
函数期间添加。一旦添加了类别,就不能删除。任何模块都可以使用 ValkeyModule_SetCommandACLCategories
将命令注册到任何已添加的类别中。
返回
- 成功添加新的 ACL 类别时返回
VALKEYMODULE_OK
。 - 失败时返回
VALKEYMODULE_ERR
。
错误时,errno 设置为
- 如果名称包含无效字符,则为 EINVAL。
- 如果类别名称已存在,则为 EBUSY。
- 如果类别数量达到最大限制 64 个类别,则为 ENOMEM。
ValkeyModule_SetCommandACLCategories
int ValkeyModule_SetCommandACLCategories(ValkeyModuleCommand *command,
const char *aclflags);
可用版本 7.2.0
ValkeyModule_SetCommandACLCategories
可用于设置模块命令和子命令的 ACL 类别。ACL 类别集应作为由空格分隔的 C 字符串 'aclflags' 传递。
例如,acl 标志 'write slow' 将命令标记为 write 和 slow ACL 类别的一部分。
成功时返回 VALKEYMODULE_OK
。错误时返回 VALKEYMODULE_ERR
。
此函数只能在 ValkeyModule_OnLoad
函数期间调用。如果在该函数之外调用,则返回错误。
ValkeyModule_SetCommandInfo
int ValkeyModule_SetCommandInfo(ValkeyModuleCommand *command,
const ValkeyModuleCommandInfo *info);
可用版本 7.0.0
设置附加命令信息。
影响 COMMAND
、COMMAND INFO
和 COMMAND DOCS
的输出、集群、ACL,并用于在调用到达模块代码之前过滤参数数量不正确的命令。
此函数可以在使用 ValkeyModule_CreateCommand
创建命令并使用 ValkeyModule_GetCommand
获取命令指针后调用。信息只能为每个命令设置一次,并且具有以下结构:
typedef struct ValkeyModuleCommandInfo {
const ValkeyModuleCommandInfoVersion *version;
const char *summary;
const char *complexity;
const char *since;
ValkeyModuleCommandHistoryEntry *history;
const char *tips;
int arity;
ValkeyModuleCommandKeySpec *key_specs;
ValkeyModuleCommandArg *args;
} ValkeyModuleCommandInfo;
除 version
外,所有字段都是可选的。字段说明:
-
version
:此字段启用与不同服务器版本的兼容性。始终将此字段设置为VALKEYMODULE_COMMAND_INFO_VERSION
。 -
summary
:命令的简短描述(可选)。 -
complexity
:复杂性描述(可选)。 -
since
:命令引入的版本(可选)。注意:指定的版本应该是模块的版本,而不是服务器版本。 -
history
:ValkeyModuleCommandHistoryEntry
数组(可选),它是一个包含以下字段的结构体const char *since; const char *changes;
since
是一个版本字符串,changes
是一个描述更改的字符串。数组以全零条目(即两个字符串都设置为 NULL 的条目)终止。 -
tips
:关于此命令的由空格分隔的提示字符串,供客户端和代理使用。请参阅 https://valkey.com.cn/topics/command-tips。 -
arity
:参数数量,包括命令名称本身。正数指定确切的参数数量,负数指定最小参数数量,因此使用 -N 表示 >= N。服务器在将调用传递给模块之前会验证调用,因此这可以替换模块命令实现内部的参数数量检查。值为 0(或省略 arity 字段)等效于如果命令有子命令则为 -2,否则为 -1。 -
key_specs
:一个ValkeyModuleCommandKeySpec
数组,以一个 memset 为零的元素终止。这是一种比旧的ValkeyModule_CreateCommand
参数firstkey
、lastkey
、keystep
更好地描述键参数位置的方案,如果这三个不足以描述键位置,则需要它。检索键位置分两步:*开始搜索*(BS),其中索引应找到第一个键;*查找键*(FK),相对于 BS 的输出,描述我们将如何哪些参数是键。此外,还有键特定的标志。Key-specs 会导致在 ValkeyModule_CreateCommand 中给定的三元组 (firstkey, lastkey, keystep) 被重新计算,但在 ValkeyModule_CreateCommand 中提供这三个参数仍然很有用,以便更好地支持 ValkeyModule_SetCommandInfo 不可用的旧服务器版本。
请注意,键规范不能完全取代“getkeys-api”(请参阅 ValkeyModule_CreateCommand、ValkeyModule_IsKeysPositionRequest 和 ValkeyModule_KeyAtPosWithFlags),因此同时提供键规范并实现 getkeys-api 可能是个好主意。
键规范具有以下结构:
typedef struct ValkeyModuleCommandKeySpec { const char *notes; uint64_t flags; ValkeyModuleKeySpecBeginSearchType begin_search_type; union { struct { int pos; } index; struct { const char *keyword; int startfrom; } keyword; } bs; ValkeyModuleKeySpecFindKeysType find_keys_type; union { struct { int lastkey; int keystep; int limit; } range; struct { int keynumidx; int firstkey; int keystep; } keynum; } fk; } ValkeyModuleCommandKeySpec;
ValkeyModuleCommandKeySpec 字段说明
-
notes
:关于此键规范的可选说明或澄清。 -
flags
:键规范标志的按位或(按位或)组合,如下所述。 -
begin_search_type
:这描述了如何发现第一个键。有两种方法可以确定第一个键VALKEYMODULE_KSPEC_BS_UNKNOWN
:无法判断键参数从何处开始。VALKEYMODULE_KSPEC_BS_INDEX
:键参数从一个常量索引开始。VALKEYMODULE_KSPEC_BS_KEYWORD
:键参数紧随特定关键字之后开始。
-
bs
:这是一个联合体,根据begin_search_type
字段的值使用index
或keyword
分支。-
bs.index.pos
:我们开始搜索键的索引。(仅限VALKEYMODULE_KSPEC_BS_INDEX
。) -
bs.keyword.keyword
:表示键参数开头的关键字(字符串)。(仅限VALKEYMODULE_KSPEC_BS_KEYWORD
。) -
bs.keyword.startfrom
:在 argv 中开始搜索的索引。可以是负数,表示从末尾开始反向搜索。示例:-2 表示从倒数第二个参数开始反向搜索。(仅限VALKEYMODULE_KSPEC_BS_KEYWORD
。)
-
-
find_keys_type
:“开始搜索”之后,这描述了哪些参数是键。策略是:VALKEYMODULE_KSPEC_BS_UNKNOWN
:无法判断键参数位于何处。VALKEYMODULE_KSPEC_FK_RANGE
:键在特定索引处结束(或相对于最后一个参数)。VALKEYMODULE_KSPEC_FK_KEYNUM
:在键本身之前某个地方有一个参数包含键参数的数量。
如果此键规范只描述一个键,则可以省略
find_keys_type
和fk
。 -
fk
:这是一个联合体,根据find_keys_type
字段的值使用range
或keynum
分支。-
fk.range
(用于VALKEYMODULE_KSPEC_FK_RANGE
):一个包含以下字段的结构体-
lastkey
:相对于起始搜索结果的最后一个键的索引。可以是负数,在这种情况下它不是相对的。-1 表示最后一个参数,-2 表示倒数第二个参数,依此类推。 -
keystep
:找到一个键后,我们应该跳过多少个参数才能找到下一个键? -
limit
:如果lastkey
是 -1,我们使用limit
按因子停止搜索。0 和 1 表示无限制。2 表示剩余参数的 1/2,3 表示 1/3,依此类推。
-
-
fk.keynum
(用于VALKEYMODULE_KSPEC_FK_KEYNUM
):一个包含以下字段的结构体-
keynumidx
:包含要传入的键数量的参数的索引,相对于起始搜索步骤的结果。 -
firstkey
:第一个键的索引,相对于起始搜索步骤的结果。(通常它就在keynumidx
之后,在这种情况下应该设置为keynumidx + 1
。) -
keystep
:找到一个键后,我们应该跳过多少个参数才能找到下一个键?
-
-
Key-spec 标志
前四个指的是命令实际对*键的值或元数据*做了什么,不一定指用户数据或如何影响它。每个键规范必须精确地有一个这些标志。任何不明确是删除、覆盖或只读的操作都将被标记为 RW。
-
VALKEYMODULE_CMD_KEY_RO
:只读。读取键的值,但不一定返回它。 -
VALKEYMODULE_CMD_KEY_RW
:读写。修改存储在键值中的数据或其元数据。 -
VALKEYMODULE_CMD_KEY_OW
:覆盖。覆盖存储在键值中的数据。 -
VALKEYMODULE_CMD_KEY_RM
:删除键。
接下来的四个指的是*键值中的用户数据*,而不是 LRU、类型、基数等元数据。它指的是对用户数据(实际输入字符串或 TTL)的逻辑操作,即被使用/返回/复制/更改。它不指元数据(如类型、计数、数据是否存在)的修改或返回。ACCESS 可以与写入操作 INSERT、DELETE 或 UPDATE 中的一个结合使用。任何不是 INSERT 或 DELETE 的写入都将是 UPDATE。
-
VALKEYMODULE_CMD_KEY_ACCESS
:从键的值中返回、复制或使用用户数据。 -
VALKEYMODULE_CMD_KEY_UPDATE
:更新值中的数据,新值可能取决于旧值。 -
VALKEYMODULE_CMD_KEY_INSERT
:向值中添加数据,不会修改或删除现有数据。 -
VALKEYMODULE_CMD_KEY_DELETE
:明确删除键值中的某些内容。
其他标志
-
VALKEYMODULE_CMD_KEY_NOT_KEY
:键实际上不是键,但在集群模式下应像键一样路由。 -
VALKEYMODULE_CMD_KEY_INCOMPLETE
:键规范可能没有指出它应该覆盖的所有键。 -
VALKEYMODULE_CMD_KEY_VARIABLE_FLAGS
:某些键可能根据参数具有不同的标志。
-
-
args
:一个ValkeyModuleCommandArg
数组,以一个 memset 为零的元素终止。ValkeyModuleCommandArg
是一个包含下面描述的字段的结构体。typedef struct ValkeyModuleCommandArg { const char *name; ValkeyModuleCommandArgType type; int key_spec_index; const char *token; const char *summary; const char *since; int flags; struct ValkeyModuleCommandArg *subargs; } ValkeyModuleCommandArg;
字段说明
-
name
:参数名称。 -
type
:参数类型。详见下文。VALKEYMODULE_ARG_TYPE_ONEOF
和VALKEYMODULE_ARG_TYPE_BLOCK
类型要求参数具有子参数,即subargs
。 -
key_spec_index
:如果type
是VALKEYMODULE_ARG_TYPE_KEY
,您必须提供与此参数关联的键规范索引。请参阅上面的key_specs
。如果参数不是键,您可以指定 -1。 -
token
:参数前面的令牌(可选)。示例:SET
中的seconds
参数有一个令牌EX
。如果参数只包含一个令牌(例如SET
中的NX
),则类型应为VALKEYMODULE_ARG_TYPE_PURE_TOKEN
,value
应为 NULL。 -
summary
:参数的简短描述(可选)。 -
since
:包含此参数的第一个版本(可选)。 -
flags
:宏VALKEYMODULE_CMD_ARG_*
的按位或组合。详见下文。 -
value
:参数的显示值。当从COMMAND
的输出创建命令语法时,应显示此字符串。如果token
不为 NULL,也应显示它。
ValkeyModuleCommandArgType
解释VALKEYMODULE_ARG_TYPE_STRING
:字符串参数。VALKEYMODULE_ARG_TYPE_INTEGER
:整数参数。VALKEYMODULE_ARG_TYPE_DOUBLE
:双精度浮点参数。VALKEYMODULE_ARG_TYPE_KEY
:表示键名的字符串参数。VALKEYMODULE_ARG_TYPE_PATTERN
:字符串,但为正则表达式模式。VALKEYMODULE_ARG_TYPE_UNIX_TIME
:整数,但为 Unix 时间戳。VALKEYMODULE_ARG_TYPE_PURE_TOKEN
:参数没有占位符。它只是一个没有值的令牌。示例:SET
命令的KEEPTTL
选项。VALKEYMODULE_ARG_TYPE_ONEOF
:当用户只能从少数几个子参数中选择一个时使用。需要subargs
。示例:SET
的NX
和XX
选项。VALKEYMODULE_ARG_TYPE_BLOCK
:当需要将多个子参数分组在一起时使用,通常是为了对它们全部应用一些东西,例如使整个组“可选”。需要subargs
。示例:ZRANGE
中的LIMIT offset count
参数。
命令参数标志的解释
VALKEYMODULE_CMD_ARG_OPTIONAL
:参数是可选的(如 SET 命令中的 GET)。VALKEYMODULE_CMD_ARG_MULTIPLE
:参数可以重复(如 DEL 中的 key)。VALKEYMODULE_CMD_ARG_MULTIPLE_TOKEN
:参数可以重复,其令牌也可以重复(如 SORT 中的GET pattern
)。
-
成功时返回 VALKEYMODULE_OK
。错误时返回 VALKEYMODULE_ERR
,且 errno
设置为 EINVAL(如果提供了无效信息)或 EEXIST(如果信息已设置)。如果信息无效,将记录警告,解释信息哪部分无效以及原因。
ValkeyModule_UpdateRuntimeArgs
int ValkeyModule_UpdateRuntimeArgs(ValkeyModuleCtx *ctx,
ValkeyModuleString **argv,
int argc);
可用版本 8.1.0
ValkeyModule_UpdateRuntimeArgs
可用于更新模块参数值。函数参数 'argc' 表示更新的参数数量,'argv' 表示更新的参数值。一旦调用 'CONFIG REWRITE' 命令,更新的参数值就可以保存到 conf 文件中。
函数始终返回 VALKEYMODULE_OK
。
模块信息和时间测量
ValkeyModule_IsModuleNameBusy
int ValkeyModule_IsModuleNameBusy(const char *name);
可用版本 4.0.3
如果模块名称被占用,则返回非零值。否则返回零。
ValkeyModule_Milliseconds
mstime_t ValkeyModule_Milliseconds(void);
可用版本 4.0.0
返回当前 UNIX 时间(毫秒)。
ValkeyModule_MonotonicMicroseconds
uint64_t ValkeyModule_MonotonicMicroseconds(void);
可用版本 7.0.0
返回相对于任意时间点的微秒计数器。
ValkeyModule_Microseconds
ustime_t ValkeyModule_Microseconds(void);
可用版本 7.2.0
返回当前 UNIX 时间(微秒)
ValkeyModule_CachedMicroseconds
ustime_t ValkeyModule_CachedMicroseconds(void);
可用版本 7.2.0
返回缓存的 UNIX 时间(微秒)。它在服务器 cron 任务和执行命令之前更新。它对于复杂的调用栈很有用,例如命令导致键空间通知,导致模块执行 ValkeyModule_Call
,导致另一个通知等。所有这些回调使用相同的时钟是有意义的。
ValkeyModule_BlockedClientMeasureTimeStart
int ValkeyModule_BlockedClientMeasureTimeStart(ValkeyModuleBlockedClient *bc);
可用版本 6.2.0
标记一个时间点,当调用 ValkeyModule_BlockedClientMeasureTimeEnd()
时,该时间点将用作计算已过去执行时间的起始时间。在同一个命令中,您可以多次调用 ValkeyModule_BlockedClientMeasureTimeStart()
和 ValkeyModule_BlockedClientMeasureTimeEnd()
,以将独立的计时区间累积到后台持续时间。此方法始终返回 VALKEYMODULE_OK
。
此函数不是线程安全的。如果同时在模块线程和阻塞回调(可能是主线程)中使用,建议使用调用者拥有的锁而不是 GIL 来保护它们。
ValkeyModule_BlockedClientMeasureTimeEnd
int ValkeyModule_BlockedClientMeasureTimeEnd(ValkeyModuleBlockedClient *bc);
可用版本 6.2.0
标记一个时间点,该点将用作计算已过去执行时间的结束时间。成功时返回 VALKEYMODULE_OK
。此方法仅在之前未定义起始时间(即未调用 ValkeyModule_BlockedClientMeasureTimeStart
)时返回 VALKEYMODULE_ERR
。
此函数不是线程安全的。如果同时在模块线程和阻塞回调(可能是主线程)中使用,建议使用调用者拥有的锁而不是 GIL 来保护它们。
ValkeyModule_Yield
void ValkeyModule_Yield(ValkeyModuleCtx *ctx,
int flags,
const char *busy_reply);
可用版本 7.0.0
此 API 允许模块在模块命令长时间阻塞执行期间,让服务器处理后台任务和一些命令。模块可以定期调用此 API。标志是以下位掩码
VALKEYMODULE_YIELD_FLAG_NONE
:无特殊标志,可以执行一些后台操作,但不能处理客户端命令。VALKEYMODULE_YIELD_FLAG_CLIENTS
:服务器也可以处理客户端命令。
busy_reply
参数是可选的,可用于控制 -BUSY
错误代码后的详细错误字符串。
当使用 VALKEYMODULE_YIELD_FLAG_CLIENTS
时,服务器只会在 busy-reply-threshold
配置定义的时间之后开始处理客户端命令,在这种情况下,服务器将开始拒绝大多数命令并返回 -BUSY
错误,但允许执行标记有 allow-busy
标志的命令。此 API 也可在线程安全上下文中使用(在锁定状态下),以及在加载期间(在 rdb_load
回调中,在这种情况下它会以 -LOADING 错误拒绝命令)
ValkeyModule_SetModuleOptions
void ValkeyModule_SetModuleOptions(ValkeyModuleCtx *ctx, int options);
可用版本 6.0.0
设置定义功能或行为的位标志。
VALKEYMODULE_OPTIONS_HANDLE_IO_ERRORS
:通常,模块不需要为此烦恼,因为如果发生读取错误,进程将直接终止。但是,设置此标志将允许 repl-diskless-load 在启用时工作。模块应在读取后、使用读取的数据之前使用 ValkeyModule_IsIOError
,并且在发生错误时,将其向上层传播,并且能够释放部分填充的值及其所有分配。
VALKEYMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED
:请参阅 ValkeyModule_SignalModifiedKey()
。
VALKEYMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD
:设置此标志表示模块了解无盘异步复制 (repl-diskless-load=swapdb),并且服务器可以在复制期间提供读取服务,而不是以 LOADING 状态阻塞。
VALKEYMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS
:声明模块希望获取嵌套键空间通知。默认情况下,服务器不会触发在键空间通知回调内部发生的键空间通知。此标志允许更改此行为并触发嵌套键空间通知。注意:如果启用,模块应自行防止无限递归。
VALKEYMODULE_OPTIONS_SKIP_COMMAND_VALIDATION
:设置此选项后,模块可以跳过命令验证。这在模块需要绕过特定操作的命令验证以减少开销或处理受信任的自定义命令逻辑的场景中非常有用。ValkeyModule_Replicate
和 ValkeyModule_EmitAOF
受此选项影响,允许它们在没有命令验证检查的情况下运行。
ValkeyModule_SignalModifiedKey
int ValkeyModule_SignalModifiedKey(ValkeyModuleCtx *ctx,
ValkeyModuleString *keyname);
可用版本 6.0.0
表示键已从用户角度修改(即,使 WATCH 和客户端缓存失效)。
除非已使用 ValkeyModule_SetModuleOptions()
设置了选项 VALKEYMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED
,否则当键打开写入后关闭时,会自动完成此操作。
模块自动内存管理
ValkeyModule_AutoMemory
void ValkeyModule_AutoMemory(ValkeyModuleCtx *ctx);
可用版本 4.0.0
启用自动内存管理。
对于希望使用自动内存的命令实现,此函数必须作为第一个函数被调用。
启用后,自动内存管理会跟踪并自动释放键、调用回复和 ValkeyModuleString
对象,一旦命令返回。在大多数情况下,这消除了调用以下函数的需要
即使启用自动内存管理,这些函数仍然可以使用,例如用于优化在循环中进行大量分配。
字符串对象 API
ValkeyModule_CreateString
ValkeyModuleString *ValkeyModule_CreateString(ValkeyModuleCtx *ctx,
const char *ptr,
size_t len);
可用版本 4.0.0
创建一个新的模块字符串对象。除非启用自动内存,否则返回的字符串必须使用 ValkeyModule_FreeString()
释放。
字符串通过复制从 ptr
开始的 len
字节创建。不保留对传入缓冲区的引用。
模块上下文 'ctx' 是可选的,如果您想在上下文范围之外创建字符串,可以将其设置为 NULL。但是,在这种情况下,自动内存管理将不可用,并且字符串内存必须手动管理。
ValkeyModule_CreateStringPrintf
ValkeyModuleString *ValkeyModule_CreateStringPrintf(ValkeyModuleCtx *ctx,
const char *fmt,
...);
可用版本 4.0.0
根据 printf 格式和参数创建一个新的模块字符串对象。除非启用自动内存,否则返回的字符串必须使用 ValkeyModule_FreeString()
释放。
字符串使用 sds 格式化函数 sdscatvprintf()
创建。
如果需要,传入的上下文 'ctx' 可以为 NULL,更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_CreateStringFromLongLong
ValkeyModuleString *ValkeyModule_CreateStringFromLongLong(ValkeyModuleCtx *ctx,
long long ll);
可用版本 4.0.0
类似于 ValkeyModule_CreateString()
,但从 long long
整数而不是缓冲区及其长度创建字符串。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
如果需要,传入的上下文 'ctx' 可以为 NULL,更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_CreateStringFromULongLong
ValkeyModuleString *ValkeyModule_CreateStringFromULongLong(ValkeyModuleCtx *ctx,
unsigned long long ull);
可用版本 7.0.3
类似于 ValkeyModule_CreateString()
,但从 unsigned long long
整数而不是缓冲区及其长度创建字符串。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
如果需要,传入的上下文 'ctx' 可以为 NULL,更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_CreateStringFromDouble
ValkeyModuleString *ValkeyModule_CreateStringFromDouble(ValkeyModuleCtx *ctx,
double d);
可用版本 6.0.0
类似于 ValkeyModule_CreateString()
,但从双精度浮点数而不是缓冲区及其长度创建字符串。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
ValkeyModule_CreateStringFromLongDouble
ValkeyModuleString *ValkeyModule_CreateStringFromLongDouble(ValkeyModuleCtx *ctx,
long double ld,
int humanfriendly);
可用版本 6.0.0
类似于 ValkeyModule_CreateString()
,但从 long double 创建字符串。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
如果需要,传入的上下文 'ctx' 可以为 NULL,更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_CreateStringFromString
ValkeyModuleString *ValkeyModule_CreateStringFromString(ValkeyModuleCtx *ctx,
const ValkeyModuleString *str);
可用版本 4.0.0
类似于 ValkeyModule_CreateString()
,但从另一个 ValkeyModuleString
创建字符串。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
如果需要,传入的上下文 'ctx' 可以为 NULL,更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_CreateStringFromStreamID
ValkeyModuleString *ValkeyModule_CreateStringFromStreamID(ValkeyModuleCtx *ctx,
const ValkeyModuleStreamID *id);
可用版本 6.2.0
从流 ID 创建字符串。除非启用自动内存,否则返回的字符串必须使用 ValkeyModule_FreeString()
释放。
如果需要,传入的上下文 ctx
可以为 NULL。更多信息请参阅 ValkeyModule_CreateString()
文档。
ValkeyModule_FreeString
void ValkeyModule_FreeString(ValkeyModuleCtx *ctx, ValkeyModuleString *str);
可用版本 4.0.0
释放通过模块 API 调用返回新字符串对象之一获取的模块字符串对象。
即使启用自动内存管理,也可以调用此函数。在这种情况下,字符串将尽快释放并从字符串池中删除,以便在最后释放。
如果字符串是使用 NULL 上下文 'ctx' 创建的,那么在释放字符串时也可以将 ctx 作为 NULL 传递(但传递上下文不会产生任何问题)。使用上下文创建的字符串也应该传递上下文来释放,因此如果您想稍后在上下文之外释放字符串,请确保使用 NULL 上下文创建它。
此 API 不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在 GIL 锁定下进行。
ValkeyModule_RetainString
void ValkeyModule_RetainString(ValkeyModuleCtx *ctx, ValkeyModuleString *str);
可用版本 4.0.0
每次调用此函数,都会使字符串 'str' 需要额外调用 ValkeyModule_FreeString()
才能真正释放字符串。请注意,通过启用模块自动内存管理获得的字符串的自动释放只算一次 ValkeyModule_FreeString()
调用(它只是自动执行)。
通常,当以下条件同时满足时,您会想要调用此函数:
- 您已启用自动内存管理。
- 您想要创建字符串对象。
- 您创建的这些字符串对象需要在创建它们的回调函数(例如命令实现)返回*之后*继续存在。
通常,您希望这样做是为了将创建的字符串对象存储到您自己的数据结构中,例如在实现新数据类型时。
请注意,当内存管理关闭时,您不需要调用任何 RetainString(),因为如果未执行 FreeString() 调用,创建字符串将始终导致字符串在回调函数返回后继续存在。
可以使用 NULL 上下文调用此函数。
当字符串将长时间保留时,最好也调用 ValkeyModule_TrimStringAllocation()
以优化内存使用。
从其他线程引用保留字符串的线程模块*必须*在字符串保留后立即显式修剪分配。不这样做可能会导致自动修剪,而自动修剪不是线程安全的。
此 API 不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在 GIL 锁定下进行。
ValkeyModule_HoldString
ValkeyModuleString *ValkeyModule_HoldString(ValkeyModuleCtx *ctx,
ValkeyModuleString *str);
可用版本 6.0.7
此函数可以代替 ValkeyModule_RetainString()
使用。两者之间的主要区别在于,此函数总是会成功,而 ValkeyModule_RetainString()
可能会因为断言而失败。
函数返回一个指向 ValkeyModuleString
的指针,该指针由调用者拥有。当上下文的自动内存管理被禁用时,需要调用 ValkeyModule_FreeString()
来释放字符串。当自动内存管理启用时,您可以调用 ValkeyModule_FreeString()
或让自动化来释放它。
此函数比 ValkeyModule_CreateStringFromString()
更高效,因为它在可能的情况下避免复制底层 ValkeyModuleString
。使用此函数的缺点是可能无法对返回的 ValkeyModuleString
使用 ValkeyModule_StringAppendBuffer()
。
可以使用 NULL 上下文调用此函数。
当字符串将长时间保留时,最好也调用 ValkeyModule_TrimStringAllocation()
以优化内存使用。
从其他线程引用被持有的字符串的线程模块*必须*在字符串被持有后立即显式修剪分配。不这样做可能导致自动修剪,而自动修剪不是线程安全的。
此 API 不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在 GIL 锁定下进行。
ValkeyModule_StringPtrLen
const char *ValkeyModule_StringPtrLen(const ValkeyModuleString *str,
size_t *len);
可用版本 4.0.0
给定一个字符串模块对象,此函数返回字符串的指针和长度。返回的指针和长度应仅用于只读访问,绝不能修改。
ValkeyModule_StringToLongLong
int ValkeyModule_StringToLongLong(const ValkeyModuleString *str,
long long *ll);
可用版本 4.0.0
将字符串转换为 long long
整数,存储在 *ll
中。成功时返回 VALKEYMODULE_OK
。如果字符串无法解析为有效且严格的 long long
(前后无空格),则返回 VALKEYMODULE_ERR
。
ValkeyModule_StringToULongLong
int ValkeyModule_StringToULongLong(const ValkeyModuleString *str,
unsigned long long *ull);
可用版本 7.0.3
将字符串转换为 unsigned long long
整数,存储在 *ull
中。成功时返回 VALKEYMODULE_OK
。如果字符串无法解析为有效且严格的 unsigned long long
(前后无空格),则返回 VALKEYMODULE_ERR
。
ValkeyModule_StringToDouble
int ValkeyModule_StringToDouble(const ValkeyModuleString *str, double *d);
可用版本 4.0.0
将字符串转换为双精度浮点数,存储在 *d
中。成功时返回 VALKEYMODULE_OK
,如果字符串不是双精度浮点值的有效字符串表示,则返回 VALKEYMODULE_ERR
。
ValkeyModule_StringToLongDouble
int ValkeyModule_StringToLongDouble(const ValkeyModuleString *str,
long double *ld);
可用版本 6.0.0
将字符串转换为长双精度浮点数,存储在 *ld
中。成功时返回 VALKEYMODULE_OK
,如果字符串不是双精度浮点值的有效字符串表示,则返回 VALKEYMODULE_ERR
。
ValkeyModule_StringToStreamID
int ValkeyModule_StringToStreamID(const ValkeyModuleString *str,
ValkeyModuleStreamID *id);
可用版本 6.2.0
将字符串转换为流 ID,存储在 *id
中。成功时返回 VALKEYMODULE_OK
,如果字符串不是流 ID 的有效字符串表示,则返回 VALKEYMODULE_ERR
。允许使用特殊 ID “+” 和 “-”。
ValkeyModule_StringCompare
int ValkeyModule_StringCompare(const ValkeyModuleString *a,
const ValkeyModuleString *b);
可用版本 4.0.0
比较两个字符串对象,如果 a < b,a == b,a > b,则分别返回 -1, 0 或 1。字符串作为两个二进制大块逐字节比较,不考虑任何编码/排序规则。
ValkeyModule_StringAppendBuffer
int ValkeyModule_StringAppendBuffer(ValkeyModuleCtx *ctx,
ValkeyModuleString *str,
const char *buf,
size_t len);
可用版本 4.0.0
将指定的缓冲区附加到字符串 'str'。字符串必须是用户创建的、仅被引用一次的字符串,否则返回 VALKEYMODULE_ERR
且操作不执行。
ValkeyModule_TrimStringAllocation
void ValkeyModule_TrimStringAllocation(ValkeyModuleString *str);
可用版本 7.0.0
修剪为 ValkeyModuleString
分配的可能多余内存。
有时,一个 ValkeyModuleString
可能为其分配了比所需更多的内存,这通常是由于从网络缓冲区构建的 argv 参数。此函数通过重新分配其内存来优化此类字符串,这对于并非短生命周期但长期保留的字符串很有用。
此操作*不是线程安全的*,只有在确保没有并发访问字符串的情况下才应调用。在字符串可能被其他线程访问之前,将其用于模块命令中的 argv 字符串通常是安全的。
目前,当模块命令返回时,服务器也可能自动修剪保留的字符串。然而,明确地执行此操作仍然是首选选项。
- 服务器的未来版本可能会放弃自动修剪。
- 当前实现的自动修剪*不是线程安全的*。后台线程操作最近保留的字符串可能会与自动修剪发生竞态条件,这可能导致数据损坏。
回复 API
这些函数用于向客户端发送回复。
大多数函数总是返回 VALKEYMODULE_OK
,因此您可以在返回命令实现时使用 'return',如下所示:
if (... some condition ...)
return ValkeyModule_ReplyWithLongLong(ctx,mycount);
集合回复函数
启动集合回复后,模块必须调用其他 ReplyWith*
风格的函数以发出集合的元素。集合类型包括:数组、映射、集合和属性。
当生成的集合元素数量事先未知时,函数可以带特殊标志 VALKEYMODULE_POSTPONED_LEN
(过去为 VALKEYMODULE_POSTPONED_ARRAY_LEN
)调用,实际元素数量可以在之后通过 ValkeyModule_ReplySet
*Length() 调用设置(这将设置最新的“开放”计数,如果有多个的话)。
ValkeyModule_WrongArity
int ValkeyModule_WrongArity(ValkeyModuleCtx *ctx);
可用版本 4.0.0
发送关于给定命令参数数量的错误,并在错误消息中引用命令名称。返回 VALKEYMODULE_OK
。
示例
if (argc != 3) return ValkeyModule_WrongArity(ctx);
ValkeyModule_ReplyWithLongLong
int ValkeyModule_ReplyWithLongLong(ValkeyModuleCtx *ctx, long long ll);
可用版本 4.0.0
向客户端发送一个整数回复,包含指定的 long long
值。该函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithError
int ValkeyModule_ReplyWithError(ValkeyModuleCtx *ctx, const char *err);
可用版本 4.0.0
回复错误 'err'。
请注意,'err' 必须包含所有错误,包括初始错误代码。该函数只提供初始的 "-",因此用法是,例如:
ValkeyModule_ReplyWithError(ctx,"ERR Wrong Type");
而不是仅仅
ValkeyModule_ReplyWithError(ctx,"Wrong Type");
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithErrorFormat
int ValkeyModule_ReplyWithErrorFormat(ValkeyModuleCtx *ctx,
const char *fmt,
...);
可用版本 7.2.0
使用 printf 格式和参数创建错误并回复。
请注意,'fmt' 必须包含所有错误,包括初始错误代码。该函数只提供初始的 "-",因此用法是,例如:
ValkeyModule_ReplyWithErrorFormat(ctx,"ERR Wrong Type: %s",type);
而不是仅仅
ValkeyModule_ReplyWithErrorFormat(ctx,"Wrong Type: %s",type);
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithSimpleString
int ValkeyModule_ReplyWithSimpleString(ValkeyModuleCtx *ctx, const char *msg);
可用版本 4.0.0
用简单字符串回复(RESP 协议中的 +... \r\n
)。这种回复仅适用于发送少量非二进制字符串,开销小,例如“OK”或类似回复。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithArray
int ValkeyModule_ReplyWithArray(ValkeyModuleCtx *ctx, long len);
可用版本 4.0.0
回复一个包含 'len' 个元素的数组类型。
启动数组回复后,模块必须调用 len
次其他 ReplyWith*
风格的函数以发出数组元素。更多详情请参见回复 API 章节。
使用 ValkeyModule_ReplySetArrayLength()
设置延迟长度。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithMap
int ValkeyModule_ReplyWithMap(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
回复一个 RESP3 Map 类型,包含 'len' 对。有关 RESP3 的更多信息,请访问 https://valkey.com.cn/topics/protocol。
启动 map 回复后,模块必须调用 len*2
次其他 ReplyWith*
风格的函数以发出 map 元素。更多详情请参见回复 API 章节。
如果连接的客户端正在使用 RESP2,回复将被转换为扁平数组。
使用 ValkeyModule_ReplySetMapLength()
设置延迟长度。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithSet
int ValkeyModule_ReplyWithSet(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
回复一个 RESP3 Set 类型,包含 'len' 个元素。有关 RESP3 的更多信息,请访问 https://valkey.com.cn/topics/protocol。
启动集合回复后,模块必须调用 len
次其他 ReplyWith*
风格的函数以发出集合元素。更多详情请参见回复 API 章节。
如果连接的客户端正在使用 RESP2,回复将被转换为数组类型。
使用 ValkeyModule_ReplySetSetLength()
设置延迟长度。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithAttribute
int ValkeyModule_ReplyWithAttribute(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
向回复添加属性(元数据)。应在添加实际回复之前完成。请参阅 https://valkey.com.cn/topics/protocol#attribute-type
启动属性回复后,模块必须调用 len*2
次其他 ReplyWith*
风格的函数以发出属性映射的元素。更多详情请参见回复 API 章节。
使用 ValkeyModule_ReplySetAttributeLength()
设置延迟长度。
RESP2 不支持,将返回 VALKEYMODULE_ERR
,否则函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithNullArray
int ValkeyModule_ReplyWithNullArray(ValkeyModuleCtx *ctx);
可用版本 6.0.0
向客户端回复一个空数组,在 RESP3 中是简单的 null,在 RESP2 中是空数组。
注意:在 RESP3 中,Null 回复和 NullArray 回复之间没有区别,因此为了防止歧义,最好避免使用此 API,而改用 ValkeyModule_ReplyWithNull
。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithEmptyArray
int ValkeyModule_ReplyWithEmptyArray(ValkeyModuleCtx *ctx);
可用版本 6.0.0
向客户端回复一个空数组。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplySetArrayLength
void ValkeyModule_ReplySetArrayLength(ValkeyModuleCtx *ctx, long len);
可用版本 4.0.0
当 ValkeyModule_ReplyWithArray()
与参数 VALKEYMODULE_POSTPONED_LEN
一起使用时,因为我们事先不知道将作为数组元素输出的项目数量,此函数将负责设置数组长度。
由于可能有多个长度未知的数组回复挂起,此函数保证始终设置以延迟方式创建的最新数组长度。
例如,为了输出像 [1,[10,20,30]] 这样的数组,我们可以这样写:
ValkeyModule_ReplyWithArray(ctx,VALKEYMODULE_POSTPONED_LEN);
ValkeyModule_ReplyWithLongLong(ctx,1);
ValkeyModule_ReplyWithArray(ctx,VALKEYMODULE_POSTPONED_LEN);
ValkeyModule_ReplyWithLongLong(ctx,10);
ValkeyModule_ReplyWithLongLong(ctx,20);
ValkeyModule_ReplyWithLongLong(ctx,30);
ValkeyModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.
ValkeyModule_ReplySetArrayLength(ctx,2); // Set len of top array
请注意,在上述示例中,没有理由推迟数组长度,因为我们生成固定数量的元素,但在实践中,代码可能使用迭代器或其他方式创建输出,因此不容易提前计算元素数量。
ValkeyModule_ReplySetMapLength
void ValkeyModule_ReplySetMapLength(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
与 ValkeyModule_ReplySetArrayLength
非常相似,只是 len
应该是映射上下文中调用的 ReplyWith*
函数数量的一半。有关 RESP3 的更多信息,请访问 https://valkey.com.cn/topics/protocol。
ValkeyModule_ReplySetSetLength
void ValkeyModule_ReplySetSetLength(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
与 ValkeyModule_ReplySetArrayLength
非常相似。有关 RESP3 的更多信息,请访问 https://valkey.com.cn/topics/protocol。
如果 ValkeyModule_ReplyWithAttribute
返回错误,则不得调用此函数。
ValkeyModule_ReplyWithAttribute
返回错误,则不得调用此函数。void ValkeyModule_ReplySetAttributeLength(ValkeyModuleCtx *ctx, long len);
可用版本 7.0.0
ValkeyModule_ReplySetAttributeLength
与 ValkeyModule_ReplySetMapLength
非常相似。有关 RESP3 的更多信息,请访问 https://valkey.com.cn/topics/protocol。
ValkeyModule_ReplyWithStringBuffer
int ValkeyModule_ReplyWithStringBuffer(ValkeyModuleCtx *ctx,
const char *buf,
size_t len);
可用版本 4.0.0
回复一个批量字符串,输入一个 C 缓冲区指针和长度。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithCString
int ValkeyModule_ReplyWithCString(ValkeyModuleCtx *ctx, const char *buf);
可用版本 5.0.6
回复一个批量字符串,输入一个假定为 null 终止的 C 缓冲区指针。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithString
int ValkeyModule_ReplyWithString(ValkeyModuleCtx *ctx,
ValkeyModuleString *str);
可用版本 4.0.0
回复一个批量字符串,输入一个 ValkeyModuleString
对象。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithEmptyString
int ValkeyModule_ReplyWithEmptyString(ValkeyModuleCtx *ctx);
可用版本 6.0.0
回复一个空字符串。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithVerbatimStringType
int ValkeyModule_ReplyWithVerbatimStringType(ValkeyModuleCtx *ctx,
const char *buf,
size_t len,
const char *ext);
可用版本 7.0.0
回复一个二进制安全字符串,该字符串不应被转义或过滤,输入一个 C 缓冲区指针、长度和一个3字符的类型/扩展名。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithVerbatimString
int ValkeyModule_ReplyWithVerbatimString(ValkeyModuleCtx *ctx,
const char *buf,
size_t len);
可用版本 6.0.0
回复一个二进制安全字符串,该字符串不应被转义或过滤,输入一个 C 缓冲区指针和长度。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithNull
int ValkeyModule_ReplyWithNull(ValkeyModuleCtx *ctx);
可用版本 4.0.0
向客户端回复 NULL。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithBool
int ValkeyModule_ReplyWithBool(ValkeyModuleCtx *ctx, int b);
可用版本 7.0.0
回复一个 RESP3 布尔类型。更多信息请访问 https://valkey.com.cn/topics/protocol。
在 RESP3 中,这是布尔类型。在 RESP2 中,它是“1”和“0”分别表示 true 和 false 的字符串响应。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithCallReply
int ValkeyModule_ReplyWithCallReply(ValkeyModuleCtx *ctx,
ValkeyModuleCallReply *reply);
可用版本 4.0.0
准确回复命令通过 ValkeyModule_Call()
返回给我们的内容。当我们需要使用 ValkeyModule_Call()
执行某些命令时,此函数非常有用,因为我们希望向客户端回复与命令获得的完全相同的回复。
返回
- 成功时返回
VALKEYMODULE_OK
。 - 如果给定回复是 RESP3 格式但客户端期望 RESP2,则返回
VALKEYMODULE_ERR
。在发生错误的情况下,模块编写者的责任是(或通过返回错误以不同方式处理)将回复转换为 RESP2。请注意,为了模块编写者的方便,可以将0
作为参数传递给ValkeyModule_Call
的 fmt 参数,以便ValkeyModuleCallReply
将以与当前客户端上下文设置的相同协议(RESP2 或 RESP3)返回。
ValkeyModule_ReplyWithDouble
int ValkeyModule_ReplyWithDouble(ValkeyModuleCtx *ctx, double d);
可用版本 4.0.0
回复一个 RESP3 双精度浮点类型。更多信息请访问 https://valkey.com.cn/topics/protocol。
发送一个通过将双精度浮点数 'd' 转换为批量字符串获得的字符串回复。此函数基本等同于将双精度浮点数转换为 C 缓冲区中的字符串,然后使用缓冲区和长度调用函数 ValkeyModule_ReplyWithStringBuffer()
。
在 RESP3 中,字符串被标记为双精度浮点数,而在 RESP2 中,它只是一个普通的字符串,用户必须自行解析。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithBigNumber
int ValkeyModule_ReplyWithBigNumber(ValkeyModuleCtx *ctx,
const char *bignum,
size_t len);
可用版本 7.0.0
回复一个 RESP3 BigNumber 类型。更多信息请访问 https://valkey.com.cn/topics/protocol。
在 RESP3 中,这是一个长度为 len
的字符串,标记为 BigNumber,但调用者需要确保它是一个有效的 BigNumber。在 RESP2 中,这只是一个普通的批量字符串响应。
函数始终返回 VALKEYMODULE_OK
。
ValkeyModule_ReplyWithLongDouble
int ValkeyModule_ReplyWithLongDouble(ValkeyModuleCtx *ctx, long double ld);
可用版本 6.0.0
发送一个通过将长双精度浮点数 'ld' 转换为批量字符串获得的字符串回复。此函数基本等同于将长双精度浮点数转换为 C 缓冲区中的字符串,然后使用缓冲区和长度调用函数 ValkeyModule_ReplyWithStringBuffer()
。双精度浮点数字符串使用人类可读的格式(请参见 networking.c 中的 addReplyHumanLongDouble
)。
函数始终返回 VALKEYMODULE_OK
。
命令复制 API
ValkeyModule_Replicate
int ValkeyModule_Replicate(ValkeyModuleCtx *ctx,
const char *cmdname,
const char *fmt,
...);
可用版本 4.0.0
复制指定的命令和参数到副本和 AOF,作为调用命令实现执行的效果。
复制的命令总是被包装在包含给定模块命令执行中所有复制命令的 MULTI/EXEC 中。但是,使用 ValkeyModule_Call()
复制的命令是第一个项目,使用 ValkeyModule_Replicate()
复制的命令将在 EXEC 之前全部跟随。
模块应尝试使用其中一个接口。
此命令与 ValkeyModule_Call()
的接口完全相同,因此必须传递一组格式说明符,后跟与提供的格式说明符匹配的参数。
更多信息请参阅 ValkeyModule_Call()
。
通过使用特殊的“A”和“R”修饰符,调用者可以从指定命令的传播中排除 AOF 或副本。否则,默认情况下,命令将在两个通道中传播。
关于从线程安全上下文调用此函数的注意事项
通常,当您从实现模块命令的回调或模块 API 提供的任何其他回调中调用此函数时,服务器会将此函数的所有调用累积在回调上下文中,并将所有命令包装在 MULTI/EXEC 事务中传播。但是,当从可以存在不确定时间并可以随意锁定/解锁的线程安全上下文调用此函数时,行为有所不同:MULTI/EXEC 包装器不会发出,并且指定的命令会立即插入到 AOF 和复制流中。
返回值
如果格式说明符无效或命令名称不属于已知命令,则命令返回 VALKEYMODULE_ERR
。
ValkeyModule_ReplicateVerbatim
int ValkeyModule_ReplicateVerbatim(ValkeyModuleCtx *ctx);
可用版本 4.0.0
此函数将精确复制客户端调用的命令。请注意,此函数不会将命令包装在 MULTI/EXEC 语句中,因此不应与其他复制命令混用。
基本上,这种形式的复制在您希望将命令精确地传播到副本和 AOF 文件中时非常有用,因为命令可以重新执行以确定性地从旧状态重新创建新状态。
函数始终返回 VALKEYMODULE_OK
。
DB 和 Key API – 通用 API
ValkeyModule_GetClientId
unsigned long long ValkeyModule_GetClientId(ValkeyModuleCtx *ctx);
可用版本 4.0.0
返回调用当前活动模块命令的当前客户端的 ID。返回的 ID 有几个保证:
- 每个不同的客户端 ID 都不同,因此如果同一个客户端多次执行模块命令,则可以识别为具有相同的 ID,否则 ID 将不同。
- ID 单调递增。连接到服务器的客户端保证获得比之前看到的任何 ID 都大的 ID。
有效 ID 范围从 1 到 2^64 - 1。如果返回 0,表示在当前调用函数的上下文中无法获取 ID。
获取 ID 后,可以使用此宏检查命令执行是否实际发生在 AOF 加载上下文中
if (ValkeyModule_IsAOFClient(ValkeyModule_GetClientId(ctx)) {
// Handle it differently.
}
ValkeyModule_GetClientUserNameById
ValkeyModuleString *ValkeyModule_GetClientUserNameById(ValkeyModuleCtx *ctx,
uint64_t id);
可用版本 6.2.1
返回具有指定客户端 ID 的客户端使用的 ACL 用户名。客户端 ID 可以通过 ValkeyModule_GetClientId()
API 获取。如果客户端不存在,则返回 NULL 并将 errno 设置为 ENOENT。如果客户端未使用 ACL 用户,则返回 NULL 并将 errno 设置为 ENOTSUP
ValkeyModule_MustObeyClient
int ValkeyModule_MustObeyClient(ValkeyModuleCtx *ctx);
可用版本 8.1.0
如果命令来自主客户端或 AOF 客户端且绝不应被拒绝,则返回 1。此检查可用于诸如跳过副本(以免与主副本不同步)或 AOF 文件中的命令验证等情况。否则(以及如果 ctx 或客户端为 NULL),返回 0。
ValkeyModule_GetClientInfoById
int ValkeyModule_GetClientInfoById(void *ci, uint64_t id);
可用版本 6.0.0
返回指定 ID 客户端的信息(该 ID 先前通过 ValkeyModule_GetClientId()
API 获取)。如果客户端存在,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
。
当客户端存在且 ci
指针不为 NULL,但指向类型为 ValkeyModuleClientInfoV1
且已正确使用 VALKEYMODULE_CLIENTINFO_INITIALIZER_V1
初始化的结构体时,该结构体将填充以下字段:
uint64_t flags; // VALKEYMODULE_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 的上下文中使用,但仍然返回相同的结构。
标志具有以下含义
VALKEYMODULE_CLIENTINFO_FLAG_SSL Client using SSL connection.
VALKEYMODULE_CLIENTINFO_FLAG_PUBSUB Client in Pub/Sub mode.
VALKEYMODULE_CLIENTINFO_FLAG_BLOCKED Client blocked in command.
VALKEYMODULE_CLIENTINFO_FLAG_TRACKING Client with keys tracking on.
VALKEYMODULE_CLIENTINFO_FLAG_UNIXSOCKET Client using unix domain socket.
VALKEYMODULE_CLIENTINFO_FLAG_MULTI Client in MULTI state.
然而,如果对任何附加信息不感兴趣,传递 NULL 只是一种检查客户端是否存在的方式。
这是当我们想要返回客户端信息结构时的正确用法:
ValkeyModuleClientInfo ci = VALKEYMODULE_CLIENTINFO_INITIALIZER;
int retval = ValkeyModule_GetClientInfoById(&ci,client_id);
if (retval == VALKEYMODULE_OK) {
printf("Address: %s\n", ci.addr);
}
ValkeyModule_GetClientNameById
ValkeyModuleString *ValkeyModule_GetClientNameById(ValkeyModuleCtx *ctx,
uint64_t id);
可用版本 7.0.3
返回给定 ID 客户端连接的名称。
如果客户端 ID 不存在,或者客户端没有与之关联的名称,则返回 NULL。
ValkeyModule_SetClientNameById
int ValkeyModule_SetClientNameById(uint64_t id, ValkeyModuleString *name);
可用版本 7.0.3
设置给定 ID 客户端的名称。这相当于客户端调用 CLIENT SETNAME name
。
成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并且 errno 设置如下:
- 如果客户端不存在,则为 ENOENT
- 如果名称包含无效字符,则为 EINVAL
ValkeyModule_PublishMessage
int ValkeyModule_PublishMessage(ValkeyModuleCtx *ctx,
ValkeyModuleString *channel,
ValkeyModuleString *message);
可用版本 6.0.0
向订阅者发布消息(请参见 PUBLISH 命令)。
ValkeyModule_PublishMessageShard
int ValkeyModule_PublishMessageShard(ValkeyModuleCtx *ctx,
ValkeyModuleString *channel,
ValkeyModuleString *message);
可用版本 7.0.0
向分片订阅者发布消息(请参见 SPUBLISH 命令)。
ValkeyModule_GetSelectedDb
int ValkeyModule_GetSelectedDb(ValkeyModuleCtx *ctx);
可用版本 4.0.0
返回当前选定的数据库。
ValkeyModule_GetContextFlags
int ValkeyModule_GetContextFlags(ValkeyModuleCtx *ctx);
可用版本 4.0.3
返回当前上下文的标志。这些标志提供了有关当前请求上下文(客户端是否是 Lua 脚本或处于 MULTI 中)以及实例通用信息(即复制和持久化)的信息。
即使上下文为 NULL,也可以调用此函数,但在这种情况下,以下标志将不会报告:
- LUA, MULTI, REPLICATED, DIRTY(更多信息请参见下文)。
可用标志及其含义
-
VALKEYMODULE_CTX_FLAGS_LUA
:该命令正在 Lua 脚本中运行 -
VALKEYMODULE_CTX_FLAGS_MULTI
:该命令正在事务内部运行 -
VALKEYMODULE_CTX_FLAGS_REPLICATED
:该命令由 PRIMARY 通过复制链接发送 -
VALKEYMODULE_CTX_FLAGS_PRIMARY
:该实例是一个主节点 -
VALKEYMODULE_CTX_FLAGS_REPLICA
:该实例是一个副本 -
VALKEYMODULE_CTX_FLAGS_READONLY
:该实例是只读的 -
VALKEYMODULE_CTX_FLAGS_CLUSTER
:该实例处于集群模式 -
VALKEYMODULE_CTX_FLAGS_AOF
:该实例已启用 AOF -
VALKEYMODULE_CTX_FLAGS_RDB
:该实例已启用 RDB -
VALKEYMODULE_CTX_FLAGS_MAXMEMORY
:该实例已设置最大内存 -
VALKEYMODULE_CTX_FLAGS_EVICT
:已设置最大内存并具有可能删除键的淘汰策略 -
VALKEYMODULE_CTX_FLAGS_OOM
:根据最大内存设置,服务器内存不足。 -
VALKEYMODULE_CTX_FLAGS_OOM_WARNING
:剩余内存不足 25% 即将达到最大内存限制。 -
VALKEYMODULE_CTX_FLAGS_LOADING
:服务器正在加载 RDB/AOF -
VALKEYMODULE_CTX_FLAGS_REPLICA_IS_STALE
:与主节点没有活动链接。 -
VALKEYMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING
:副本正在尝试连接主节点。 -
VALKEYMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING
:主节点 -> 副本 RDB 传输正在进行中。 -
VALKEYMODULE_CTX_FLAGS_REPLICA_IS_ONLINE
:副本与其主节点有活动链接。这与 STALE 状态相反。 -
VALKEYMODULE_CTX_FLAGS_ACTIVE_CHILD
:当前有后台进程活跃(RDB、AUX 或模块)。 -
VALKEYMODULE_CTX_FLAGS_MULTI_DIRTY
:由于脏 CAS(触摸过的键),下一次 EXEC 将失败。 -
VALKEYMODULE_CTX_FLAGS_IS_CHILD
:服务器当前正在后台子进程中运行。 -
VALKEYMODULE_CTX_FLAGS_RESP3
:指示连接到此上下文的客户端正在使用 RESP3。 -
VALKEYMODULE_CTX_FLAGS_SERVER_STARTUP
:实例正在启动
ValkeyModule_AvoidReplicaTraffic
int ValkeyModule_AvoidReplicaTraffic(void);
可用版本 6.0.0
如果客户端向服务器发送了 CLIENT PAUSE 命令,或者集群执行了手动故障转移,暂停了客户端,则返回 true。当有带副本的主节点,并且希望写入,而不向复制通道添加更多数据时,这是必需的,以便副本的复制偏移量与主节点的偏移量匹配。发生这种情况时,可以安全地进行主节点故障转移而不会丢失数据。
然而,模块可能会通过在命令执行之外的上下文中,例如在超时回调、线程安全上下文等中,调用带有“!”标志的 ValkeyModule_Call()
,或者调用 ValkeyModule_Replicate()
来生成流量。当模块生成过多流量时,主节点和副本偏移量将难以匹配,因为复制通道中有更多数据需要发送。
因此,当此函数返回 true 时,模块可能希望避免非常繁重的后台工作,这些工作会向复制通道创建数据。这主要适用于具有后台垃圾收集任务,或在计时器回调或其他定期回调中定期进行写入并复制这些写入的模块。
ValkeyModule_SelectDb
int ValkeyModule_SelectDb(ValkeyModuleCtx *ctx, int newid);
可用版本 4.0.0
更改当前选定的数据库。如果 ID 超出范围则返回错误。
请注意,即使调用此函数的模块实现的命令返回后,客户端仍将保留当前选定的数据库。
如果模块命令希望更改其他数据库中的内容并返回到原始数据库,则应事先调用 ValkeyModule_GetSelectedDb()
,以便在返回前恢复旧的数据库编号。
ValkeyModule_KeyExists
int ValkeyModule_KeyExists(ValkeyModuleCtx *ctx, robj *keyname);
可用版本 7.0.0
检查键是否存在,不影响其上次访问时间。
这相当于使用模式 VALKEYMODULE_READ
| VALKEYMODULE_OPEN_KEY_NOTOUCH
调用 ValkeyModule_OpenKey
,然后检查是否返回 NULL,如果不是,则对打开的键调用 ValkeyModule_CloseKey
。
ValkeyModule_OpenKey
ValkeyModuleKey *ValkeyModule_OpenKey(ValkeyModuleCtx *ctx,
robj *keyname,
int mode);
可用版本 4.0.0
返回一个表示键的句柄,以便可以使用键句柄作为参数调用其他 API 来执行键上的操作。
返回值是表示键的句柄,必须使用 ValkeyModule_CloseKey()
关闭该句柄。
如果键不存在且请求了 VALKEYMODULE_WRITE
模式,则仍会返回句柄,因为可以在尚未存在的键上执行操作(例如,在列表推送操作后会创建该键)。如果模式仅为 VALKEYMODULE_READ
,而键不存在,则返回 NULL。但是,即使在 NULL 值上调用 ValkeyModule_CloseKey()
和 ValkeyModule_KeyType()
也是安全的。
可在 mode 参数下传递给 API 的额外标志
VALKEYMODULE_OPEN_KEY_NOTOUCH
- 打开键时避免触及键的 LRU/LFU。VALKEYMODULE_OPEN_KEY_NONOTIFY
- 键丢失时不触发键空间事件。VALKEYMODULE_OPEN_KEY_NOSTATS
- 不更新键空间命中/未命中计数器。VALKEYMODULE_OPEN_KEY_NOEXPIRE
- 避免删除惰性过期的键。VALKEYMODULE_OPEN_KEY_NOEFFECTS
- 避免获取键的任何副作用。
ValkeyModule_GetOpenKeyModesAll
int ValkeyModule_GetOpenKeyModesAll(void);
可用版本 7.2.0
返回完整的 OpenKey 模式掩码,模块可以使用返回值检查所使用的服务器版本是否支持某些 OpenKey 模式集。例如
int supportedMode = ValkeyModule_GetOpenKeyModesAll();
if (supportedMode & VALKEYMODULE_OPEN_KEY_NOTOUCH) {
// VALKEYMODULE_OPEN_KEY_NOTOUCH is supported
} else{
// VALKEYMODULE_OPEN_KEY_NOTOUCH is not supported
}
ValkeyModule_CloseKey
void ValkeyModule_CloseKey(ValkeyModuleKey *key);
可用版本 4.0.0
关闭一个键句柄。键句柄被释放后不应再访问。
ValkeyModule_KeyType
int ValkeyModule_KeyType(ValkeyModuleKey *key);
可用版本 4.0.0
返回键的类型。如果键指针为 NULL,则返回 VALKEYMODULE_KEYTYPE_EMPTY
。
ValkeyModule_ValueLength
size_t ValkeyModule_ValueLength(ValkeyModuleKey *key);
可用版本 4.0.0
返回与键关联的值的长度。对于字符串,这是字符串的长度。对于所有其他类型,是元素的数量(哈希只计算键)。
如果键指针为 NULL 或键为空,则返回零。
ValkeyModule_DeleteKey
int ValkeyModule_DeleteKey(ValkeyModuleKey *key);
可用版本 4.0.0
如果键已打开用于写入,则将其删除,并将键设置为接受作为空键的新写入(该空键将按需创建)。成功时返回 VALKEYMODULE_OK
。如果键未打开用于写入,则返回 VALKEYMODULE_ERR
。
ValkeyModule_UnlinkKey
int ValkeyModule_UnlinkKey(ValkeyModuleKey *key);
可用版本 4.0.7
如果键已打开用于写入,则取消链接(即以非阻塞方式删除,不立即回收内存),并将键设置为接受作为空键的新写入(该空键将按需创建)。成功时返回 VALKEYMODULE_OK
。如果键未打开用于写入,则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetExpire
mstime_t ValkeyModule_GetExpire(ValkeyModuleKey *key);
可用版本 4.0.0
返回键的过期值,以剩余 TTL 毫秒表示。如果键没有关联 TTL 或键为空,则返回 VALKEYMODULE_NO_EXPIRE
。
ValkeyModule_SetExpire
int ValkeyModule_SetExpire(ValkeyModuleKey *key, mstime_t expire);
可用版本 4.0.0
为键设置新的过期时间。如果设置了特殊过期时间 VALKEYMODULE_NO_EXPIRE
,则如果存在过期时间,则会取消(与 PERSIST 命令相同)。
请注意,过期时间必须提供为正整数,表示键应具有的 TTL 毫秒数。
成功时函数返回 VALKEYMODULE_OK
,如果键未打开用于写入或为空键,则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetAbsExpire
mstime_t ValkeyModule_GetAbsExpire(ValkeyModuleKey *key);
可用版本 6.2.2
返回键的过期值,作为绝对 Unix 时间戳。如果键没有关联 TTL 或键为空,则返回 VALKEYMODULE_NO_EXPIRE
。
ValkeyModule_SetAbsExpire
int ValkeyModule_SetAbsExpire(ValkeyModuleKey *key, mstime_t expire);
可用版本 6.2.2
为键设置新的过期时间。如果设置了特殊过期时间 VALKEYMODULE_NO_EXPIRE
,则如果存在过期时间,则会取消(与 PERSIST 命令相同)。
请注意,过期时间必须提供为正整数,表示键应具有的绝对 Unix 时间戳。
成功时函数返回 VALKEYMODULE_OK
,如果键未打开用于写入或为空键,则返回 VALKEYMODULE_ERR
。
ValkeyModule_ResetDataset
void ValkeyModule_ResetDataset(int restart_aof, int async);
可用版本 6.0.0
执行类似于 FLUSHALL 的操作,并可选地启动一个新的 AOF 文件(如果启用)。如果 restart_aof
为 true,则必须确保触发此调用的命令未传播到 AOF 文件。当 async 设置为 true 时,数据库内容将由后台线程释放。
ValkeyModule_DbSize
unsigned long long ValkeyModule_DbSize(ValkeyModuleCtx *ctx);
可用版本 6.0.0
返回当前数据库中的键数量。
ValkeyModule_RandomKey
ValkeyModuleString *ValkeyModule_RandomKey(ValkeyModuleCtx *ctx);
可用版本 6.0.0
返回随机键的名称,如果当前数据库为空则返回 NULL。
ValkeyModule_GetKeyNameFromOptCtx
const ValkeyModuleString *ValkeyModule_GetKeyNameFromOptCtx(ValkeyModuleKeyOptCtx *ctx);
可用版本 7.0.0
返回当前正在处理的键的名称。
ValkeyModule_GetToKeyNameFromOptCtx
const ValkeyModuleString *ValkeyModule_GetToKeyNameFromOptCtx(ValkeyModuleKeyOptCtx *ctx);
可用版本 7.0.0
返回当前正在处理的目标键的名称。
ValkeyModule_GetDbIdFromOptCtx
int ValkeyModule_GetDbIdFromOptCtx(ValkeyModuleKeyOptCtx *ctx);
可用版本 7.0.0
返回当前正在处理的 dbid。
ValkeyModule_GetToDbIdFromOptCtx
int ValkeyModule_GetToDbIdFromOptCtx(ValkeyModuleKeyOptCtx *ctx);
可用版本 7.0.0
返回当前正在处理的目标 dbid。
字符串类型 Key API
另请参阅 ValkeyModule_ValueLength()
,它返回字符串的长度。
ValkeyModule_StringSet
int ValkeyModule_StringSet(ValkeyModuleKey *key, ValkeyModuleString *str);
可用版本 4.0.0
如果键已打开用于写入,则将指定的字符串 'str' 设置为键的值,如果存在旧值则删除。成功时返回 VALKEYMODULE_OK
。如果键未打开用于写入或存在活动迭代器,则返回 VALKEYMODULE_ERR
。
ValkeyModule_StringDMA
char *ValkeyModule_StringDMA(ValkeyModuleKey *key, size_t *len, int mode);
可用版本 4.0.0
准备与键关联的字符串值以进行 DMA 访问,并返回一个指针和大小(通过引用),用户可以使用它们直接通过指针就地读取或修改字符串。
'mode' 由以下标志按位或组成
VALKEYMODULE_READ -- Read access
VALKEYMODULE_WRITE -- Write access
如果未请求写入 DMA,则返回的指针应仅以只读方式访问。
出错时(类型错误)返回 NULL。
DMA 访问规则
-
从获取指针的那一刻起,只要我们想使用 DMA 访问来读取或修改字符串,就不能调用其他键写入函数。
-
每次调用
ValkeyModule_StringTruncate()
时,为了继续进行 DMA 访问,应再次调用ValkeyModule_StringDMA()
以重新获取新的指针和长度。 -
如果返回的指针不是 NULL,但长度为零,则不能触及任何字节(字符串为空,或键本身为空),因此如果需要扩大字符串,则应使用
ValkeyModule_StringTruncate()
调用,然后再次调用 StringDMA() 获取指针。
ValkeyModule_StringTruncate
int ValkeyModule_StringTruncate(ValkeyModuleKey *key, size_t newlen);
可用版本 4.0.0
如果键已打开用于写入且为字符串类型,则调整其大小,如果新长度大于旧长度,则用零字节填充。
在此调用之后,必须再次调用 ValkeyModule_StringDMA()
以继续使用新指针进行 DMA 访问。
成功时函数返回 VALKEYMODULE_OK
,出错时返回 VALKEYMODULE_ERR
,即键未打开用于写入、不是字符串或请求调整大小超过 512 MB。
如果键为空,则会创建一个带有新字符串值的字符串键,除非请求的新长度值为零。
列表类型 Key API
许多列表函数通过索引访问元素。由于列表本质上是双向链表,通过索引访问元素通常是 O(N) 操作。但是,如果元素是顺序访问或索引接近,则函数会进行优化,从上一个索引而不是从列表两端查找索引。
这使得可以使用简单的 for 循环高效地进行迭代
long n = ValkeyModule_ValueLength(key);
for (long i = 0; i < n; i++) {
ValkeyModuleString *elem = ValkeyModule_ListGet(key, i);
// Do stuff...
}
请注意,使用 ValkeyModule_ListPop
、ValkeyModule_ListSet
或 ValkeyModule_ListInsert
修改列表后,内部迭代器会失效,因此下一个操作将需要线性查找。
以任何其他方式修改列表,例如使用 ValkeyModule_Call()
,同时键处于打开状态将混淆内部迭代器,并可能在此类修改后使用键时导致问题。在这种情况下,必须重新打开键。
另请参阅 ValkeyModule_ValueLength()
,它返回列表的长度。
ValkeyModule_ListPush
int ValkeyModule_ListPush(ValkeyModuleKey *key,
int where,
ValkeyModuleString *ele);
可用版本 4.0.0
根据 'where' 参数(VALKEYMODULE_LIST_HEAD
或 VALKEYMODULE_LIST_TAIL
)将元素推入列表的头部或尾部。如果键引用了一个打开用于写入的空键,则创建该键。成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果 key 或 ele 为 NULL,则为 EINVAL。
- 如果键是列表以外的其他类型,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
注意:在 Redis OSS 7.0 之前,此函数未设置 errno
。
ValkeyModule_ListPop
ValkeyModuleString *ValkeyModule_ListPop(ValkeyModuleKey *key, int where);
可用版本 4.0.0
从列表中弹出一个元素,并将其作为模块字符串对象返回,用户应使用 ValkeyModule_FreeString()
或通过启用自动内存来释放它。where
参数指定元素应从列表的开头还是末尾弹出(VALKEYMODULE_LIST_HEAD
或 VALKEYMODULE_LIST_TAIL
)。失败时,命令返回 NULL 并按如下设置 errno
- 如果 key 为 NULL,则为 EINVAL。
- 如果键为空或为列表以外的其他类型,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
注意:在 Redis OSS 7.0 之前,此函数未设置 errno
。
ValkeyModule_ListGet
ValkeyModuleString *ValkeyModule_ListGet(ValkeyModuleKey *key, long index);
可用版本 7.0.0
返回存储在 key
处的列表中索引 index
处的元素,类似于 LINDEX 命令。该元素应使用 ValkeyModule_FreeString()
或使用自动内存管理释放。
索引是从零开始的,所以 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。在这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
在给定键和索引处未找到值时,返回 NULL 并按如下设置 errno
- 如果 key 为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键未打开用于读取,则为 EBADF。
- 如果索引在列表中不是有效索引,则为 EDOM。
ValkeyModule_ListSet
int ValkeyModule_ListSet(ValkeyModuleKey *key,
long index,
ValkeyModuleString *value);
可用版本 7.0.0
替换存储在 key
处的列表中索引 index
处的元素。
索引是从零开始的,所以 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。在这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。
成功时,返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果 key 或 value 为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
- 如果索引在列表中不是有效索引,则为 EDOM。
ValkeyModule_ListInsert
int ValkeyModule_ListInsert(ValkeyModuleKey *key,
long index,
ValkeyModuleString *value);
可用版本 7.0.0
在给定索引处插入一个元素。
索引是从零开始的,所以 0 表示第一个元素,1 表示第二个元素,依此类推。负索引可用于指定从列表尾部开始的元素。在这里,-1 表示最后一个元素,-2 表示倒数第二个元素,依此类推。索引是插入后元素的索引。
成功时,返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果 key 或 value 为 NULL,则为 EINVAL。
- 如果键是列表以外的其他类型,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
- 如果索引在列表中不是有效索引,则为 EDOM。
ValkeyModule_ListDelete
int ValkeyModule_ListDelete(ValkeyModuleKey *key, long index);
可用版本 7.0.0
删除给定索引处的元素。索引从 0 开始。也可以使用负索引,从列表末尾开始计数。
成功时,返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果 key 或 value 为 NULL,则为 EINVAL。
- 如果键不是列表,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
- 如果索引在列表中不是有效索引,则为 EDOM。
有序集合类型 Key API
另请参阅 ValkeyModule_ValueLength()
,它返回有序集合的长度。
ValkeyModule_ZsetAdd
int ValkeyModule_ZsetAdd(ValkeyModuleKey *key,
double score,
ValkeyModuleString *ele,
int *flagsptr);
可用版本 4.0.0
向有序集合中添加一个新元素,并指定 'score'。如果元素已存在,则更新分数。
如果键是为写入而设置的空开放键,则在值处创建一个新的有序集合。
可以通过指针将附加标志传递给函数,这些标志既用于接收输入,也用于函数返回时通信状态。如果没有使用特殊标志,'flagsptr' 可以为 NULL。
输入标志是
VALKEYMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
VALKEYMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
VALKEYMODULE_ZADD_GT: If element exists, new score must be greater than the current score.
Do nothing otherwise. Can optionally be combined with XX.
VALKEYMODULE_ZADD_LT: If element exists, new score must be less than the current score.
Do nothing otherwise. Can optionally be combined with XX.
输出标志是
VALKEYMODULE_ZADD_ADDED: The new element was added to the sorted set.
VALKEYMODULE_ZADD_UPDATED: The score of the element was updated.
VALKEYMODULE_ZADD_NOP: No operation was performed because XX or NX flags.
成功时函数返回 VALKEYMODULE_OK
。在以下错误情况下返回 VALKEYMODULE_ERR
- 键未打开用于写入。
- 键的类型错误。
- 'score' 双精度值不是数字(NaN)。
ValkeyModule_ZsetIncrby
int ValkeyModule_ZsetIncrby(ValkeyModuleKey *key,
double score,
ValkeyModuleString *ele,
int *flagsptr,
double *newscore);
可用版本 4.0.0
此函数与 ValkeyModule_ZsetAdd()
完全相同,但它不是设置新分数,而是增加现有元素的分数,如果元素尚不存在,则在假设旧分数为零的情况下添加该元素。
输入和输出标志以及返回值具有完全相同的含义,唯一的区别是此函数即使在 'score' 是有效双精度数字的情况下,也会返回 VALKEYMODULE_ERR
,但将其添加到现有分数会导致 NaN(不是数字)条件。
如果 'newscore' 不为 NULL,则此函数有一个附加字段 'newscore',如果没有返回错误,则会填充元素的增量后新分数。
ValkeyModule_ZsetRem
int ValkeyModule_ZsetRem(ValkeyModuleKey *key,
ValkeyModuleString *ele,
int *deleted);
可用版本 4.0.0
从有序集合中删除指定的元素。函数成功时返回 VALKEYMODULE_OK
,在以下任一条件下返回 VALKEYMODULE_ERR
- 键未打开用于写入。
- 键的类型错误。
返回值并不指示元素是否确实被删除(因为它存在),而只指示函数是否成功执行。
为了知道元素是否被删除,必须传递附加参数 'deleted',它通过引用填充整数,根据操作结果将其设置为 1 或 0。如果调用者不关心元素是否真的被删除,则 'deleted' 参数可以为 NULL。
空键将通过不执行任何操作来正确处理。
ValkeyModule_ZsetScore
int ValkeyModule_ZsetScore(ValkeyModuleKey *key,
ValkeyModuleString *ele,
double *score);
可用版本 4.0.0
成功时检索与有序集合元素 'ele' 关联的双精度分数,并返回 VALKEYMODULE_OK
。否则,返回 VALKEYMODULE_ERR
以表示以下条件之一
- 有序集合中不存在此类元素 'ele'。
- 键不是有序集合。
- 键是开放的空键。
有序集合迭代器 Key API
ValkeyModule_ZsetRangeStop
void ValkeyModule_ZsetRangeStop(ValkeyModuleKey *key);
可用版本 4.0.0
停止有序集合迭代。
ValkeyModule_ZsetRangeEndReached
int ValkeyModule_ZsetRangeEndReached(ValkeyModuleKey *key);
可用版本 4.0.0
返回“范围结束”标志值以指示迭代结束。
ValkeyModule_ZsetFirstInScoreRange
int ValkeyModule_ZsetFirstInScoreRange(ValkeyModuleKey *key,
double min,
double max,
int minex,
int maxex);
可用版本 4.0.0
设置一个有序集合迭代器,查找指定范围内的第一个元素。如果迭代器正确初始化,则返回 VALKEYMODULE_OK
,否则在以下条件下返回 VALKEYMODULE_ERR
- 键中存储的值不是有序集合,或键为空。
范围根据两个双精度值 'min' 和 'max' 指定。两者都可以使用以下两个宏表示无穷大
VALKEYMODULE_POSITIVE_INFINITE
表示正无穷大值VALKEYMODULE_NEGATIVE_INFINITE
表示负无穷大值
'minex' 和 'maxex' 参数(如果为 true)分别设置一个范围,其中最小值和最大值是排他性的(不包含)而不是包含性的。
ValkeyModule_ZsetLastInScoreRange
int ValkeyModule_ZsetLastInScoreRange(ValkeyModuleKey *key,
double min,
double max,
int minex,
int maxex);
可用版本 4.0.0
与 ValkeyModule_ZsetFirstInScoreRange()
完全相同,但选择范围的最后一个元素作为迭代的起点。
ValkeyModule_ZsetFirstInLexRange
int ValkeyModule_ZsetFirstInLexRange(ValkeyModuleKey *key,
ValkeyModuleString *min,
ValkeyModuleString *max);
可用版本 4.0.0
设置一个有序集合迭代器,查找指定字典序范围内的第一个元素。如果迭代器正确初始化,则返回 VALKEYMODULE_OK
,否则在以下条件下返回 VALKEYMODULE_ERR
- 键中存储的值不是有序集合,或键为空。
- 字典序范围 'min' 和 'max' 格式无效。
'min' 和 'max' 应以与传递给 ZRANGEBYLEX 命令的参数相同的格式作为两个 ValkeyModuleString
对象提供。函数不拥有这些对象,因此在设置迭代器后可以尽快释放它们。
ValkeyModule_ZsetLastInLexRange
int ValkeyModule_ZsetLastInLexRange(ValkeyModuleKey *key,
ValkeyModuleString *min,
ValkeyModuleString *max);
可用版本 4.0.0
与 ValkeyModule_ZsetFirstInLexRange()
完全相同,但选择范围的最后一个元素作为迭代的起点。
ValkeyModule_ZsetRangeCurrentElement
ValkeyModuleString *ValkeyModule_ZsetRangeCurrentElement(ValkeyModuleKey *key,
double *score);
可用版本 4.0.0
返回活动有序集合迭代器的当前有序集合元素,如果迭代器中指定的范围不包含任何元素,则返回 NULL。
ValkeyModule_ZsetRangeNext
int ValkeyModule_ZsetRangeNext(ValkeyModuleKey *key);
可用版本 4.0.0
转到有序集合迭代器的下一个元素。如果存在下一个元素,则返回 1;如果已位于最新元素或范围根本不包含任何项,则返回 0。
ValkeyModule_ZsetRangePrev
int ValkeyModule_ZsetRangePrev(ValkeyModuleKey *key);
可用版本 4.0.0
转到有序集合迭代器的上一个元素。如果存在上一个元素,则返回 1;如果已位于第一个元素或范围根本不包含任何项,则返回 0。
哈希类型 Key API
另请参阅 ValkeyModule_ValueLength()
,它返回哈希中字段的数量。
ValkeyModule_HashSet
int ValkeyModule_HashSet(ValkeyModuleKey *key, int flags, ...);
可用版本 4.0.0
将指定哈希字段的字段设置为指定值。如果键是打开用于写入的空键,则会使用空哈希值创建它,以便设置指定的字段。
该函数是可变参数的,用户必须指定字段名和值的对,两者都作为 ValkeyModuleString
指针(除非设置了 CFIELD 选项,稍后会介绍)。在字段/值指针对的末尾,必须指定 NULL 作为最后一个参数,以表示可变参数函数的参数结束。
设置哈希 argv[1] 到值 argv[2] 的示例
ValkeyModule_HashSet(key,VALKEYMODULE_HASH_NONE,argv[1],argv[2],NULL);
该函数还可以用于通过将字段设置为 VALKEYMODULE_HASH_DELETE
的指定值来删除字段(如果它们存在)
ValkeyModule_HashSet(key,VALKEYMODULE_HASH_NONE,argv[1],
VALKEYMODULE_HASH_DELETE,NULL);
命令的行为随指定的标志而变化,如果不需要特殊行为,则可以将标志设置为 VALKEYMODULE_HASH_NONE
。
VALKEYMODULE_HASH_NX: The operation is performed only if the field was not
already existing in the hash.
VALKEYMODULE_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.
VALKEYMODULE_HASH_CFIELDS: The field names passed are null terminated C
strings instead of ValkeyModuleString objects.
VALKEYMODULE_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 OSS
6.2.)
除非指定了 NX,否则命令会用新值覆盖旧的字段值。
当使用 VALKEYMODULE_HASH_CFIELDS
时,字段名使用普通的 C 字符串报告,因此例如要删除字段 "foo",可以使用以下代码
ValkeyModule_HashSet(key,VALKEYMODULE_HASH_CFIELDS,"foo",
VALKEYMODULE_HASH_DELETE,NULL);
返回值
调用前哈希中存在的字段数量,这些字段已更新(其旧值已被新值替换)或已删除。如果设置了 VALKEYMODULE_HASH_COUNT_ALL
标志,则未先前存在于哈希中的插入字段也会被计数。
如果返回值为零,则 errno
按如下设置(自 Redis OSS 6.2 起)
- 如果设置了任何未知标志或 key 为 NULL,则为 EINVAL。
- 如果键与非哈希值关联,则为 ENOTSUP。
- 如果键未打开用于写入,则为 EBADF。
- 如果未计数任何字段(如上述返回值所述),则为 ENOENT。这实际上不是错误。如果所有字段都刚刚创建并且未设置
COUNT_ALL
标志,或者由于 NX 和 XX 标志而阻止了更改,则返回值为零。
注意:此函数的返回值语义在 Redis OSS 6.2 和旧版本之间存在很大差异。使用它的模块应确定服务器版本并相应地处理它。
ValkeyModule_HashGet
int ValkeyModule_HashGet(ValkeyModuleKey *key, int flags, ...);
可用版本 4.0.0
从哈希值中获取字段。此函数使用可变数量的参数调用,字段名(作为 ValkeyModuleString
指针)与指向 ValkeyModuleString
指针的指针交替出现,如果字段存在,则该指针设置为字段的值,如果字段不存在,则设置为 NULL。在字段/值指针对的末尾,必须指定 NULL 作为最后一个参数,以表示可变参数函数的参数结束。
这是一个使用示例
ValkeyModuleString *first, *second;
ValkeyModule_HashGet(mykey,VALKEYMODULE_HASH_NONE,argv[1],&first,
argv[2],&second,NULL);
与 ValkeyModule_HashSet()
一样,可以通过传递与 VALKEYMODULE_HASH_NONE
不同的标志来指定命令的行为
VALKEYMODULE_HASH_CFIELDS
:字段名作为以 null 结尾的 C 字符串。
VALKEYMODULE_HASH_EXISTS
:不是设置字段的值(期望 ValkeyModuleString
指针的指针),函数只是报告字段是否存在,并期望一个整数指针作为每对的第二个元素。
VALKEYMODULE_HASH_CFIELDS
的示例
ValkeyModuleString *username, *hashedpass;
ValkeyModule_HashGet(mykey,VALKEYMODULE_HASH_CFIELDS,"username",&username,"hp",&hashedpass, NULL);
VALKEYMODULE_HASH_EXISTS
的示例
int exists;
ValkeyModule_HashGet(mykey,VALKEYMODULE_HASH_EXISTS,argv[1],&exists,NULL);
成功时函数返回 VALKEYMODULE_OK
,如果键不是哈希值则返回 VALKEYMODULE_ERR
。
内存管理
返回的 ValkeyModuleString
对象应使用 ValkeyModule_FreeString()
释放,或通过启用自动内存管理。
流类型 Key API
流简介,请参见 https://valkey.com.cn/topics/streams-intro。
在流函数中使用的 ValkeyModuleStreamID
类型是一个包含两个 64 位字段的结构体,定义如下
typedef struct ValkeyModuleStreamID {
uint64_t ms;
uint64_t seq;
} ValkeyModuleStreamID;
另请参阅 ValkeyModule_ValueLength()
,它返回流的长度,以及转换函数 ValkeyModule_StringToStreamID()
和 ValkeyModule_CreateStringFromStreamID()
。
ValkeyModule_StreamAdd
int ValkeyModule_StreamAdd(ValkeyModuleKey *key,
int flags,
ValkeyModuleStreamID *id,
ValkeyModuleString **argv,
long numfields);
可用版本 6.2.0
向流中添加条目。类似于不修剪的 XADD。
key
:流存储(或将要存储)的键flags
:一个位字段,包含VALKEYMODULE_STREAM_ADD_AUTOID
:自动分配流 ID,类似于 XADD 命令中的*
。
id
:如果设置了AUTOID
标志,则在此处返回分配的 ID。如果您不关心接收 ID,则AUTOID
设置时可以为 NULL。如果未设置AUTOID
,则这是请求的 ID。argv
:指向大小为numfields * 2
的数组的指针,包含字段和值。numfields
:argv
中字段-值对的数量。
如果添加了条目,则返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时参数无效,则为 EINVAL
- 如果键引用了除流之外的其他类型的值,则为 ENOTSUP
- 如果键未打开用于写入,则为 EBADF
- 如果给定 ID 为 0-0 或不大于流中所有其他 ID(仅当未设置 AUTOID 标志时),则为 EDOM
- 如果流已达到最后一个可能的 ID,则为 EFBIG
- 如果元素太大而无法存储,则为 ERANGE。
ValkeyModule_StreamDelete
int ValkeyModule_StreamDelete(ValkeyModuleKey *key, ValkeyModuleStreamID *id);
可用版本 6.2.0
从流中删除一个条目。
key
:已打开用于写入的键,未启动流迭代器。id
:要删除的条目的流 ID。
成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时参数无效,则为 EINVAL
- 如果键引用了除流之外的其他类型的值或键为空,则为 ENOTSUP
- 如果键未打开用于写入或键关联了流迭代器,则为 EBADF
- 如果不存在给定流 ID 的条目,则为 ENOENT
另请参阅 ValkeyModule_StreamIteratorDelete()
,用于在使用流迭代器时删除当前条目。
ValkeyModule_StreamIteratorStart
int ValkeyModule_StreamIteratorStart(ValkeyModuleKey *key,
int flags,
ValkeyModuleStreamID *start,
ValkeyModuleStreamID *end);
可用版本 6.2.0
设置流迭代器。
key
:使用ValkeyModule_OpenKey()
打开用于读取的流键。标志
:VALKEYMODULE_STREAM_ITERATOR_EXCLUSIVE
:迭代范围不包括start
和end
。VALKEYMODULE_STREAM_ITERATOR_REVERSE
:以相反顺序迭代,从范围的end
开始。
start
:范围的下界。对于流的开头,使用 NULL。end
:范围的上界。对于流的结尾,使用 NULL。
成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时参数无效,则为 EINVAL
- 如果键引用了除流之外的其他类型的值或键为空,则为 ENOTSUP
- 如果键未打开用于写入或键已关联流迭代器,则为 EBADF
- 如果
start
或end
超出有效范围,则为 EDOM
成功时返回 VALKEYMODULE_OK
,如果键不引用流或给定参数无效,则返回 VALKEYMODULE_ERR
。
流 ID 使用 ValkeyModule_StreamIteratorNextID()
检索,对于每个流 ID,字段和值使用 ValkeyModule_StreamIteratorNextField()
检索。迭代器通过调用 ValkeyModule_StreamIteratorStop()
释放。
示例(省略错误处理)
ValkeyModule_StreamIteratorStart(key, 0, startid_ptr, endid_ptr);
ValkeyModuleStreamID id;
long numfields;
while (ValkeyModule_StreamIteratorNextID(key, &id, &numfields) ==
VALKEYMODULE_OK) {
ValkeyModuleString *field, *value;
while (ValkeyModule_StreamIteratorNextField(key, &field, &value) ==
VALKEYMODULE_OK) {
//
// ... Do stuff ...
//
ValkeyModule_FreeString(ctx, field);
ValkeyModule_FreeString(ctx, value);
}
}
ValkeyModule_StreamIteratorStop(key);
ValkeyModule_StreamIteratorStop
int ValkeyModule_StreamIteratorStop(ValkeyModuleKey *key);
可用版本 6.2.0
停止使用 ValkeyModule_StreamIteratorStart()
创建的流迭代器并回收其内存。
成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时 key 为 NULL,则为 EINVAL
- 如果键引用了除流之外的其他类型的值或键为空,则为 ENOTSUP
- 如果键未打开用于写入或键没有关联的流迭代器,则为 EBADF
ValkeyModule_StreamIteratorNextID
int ValkeyModule_StreamIteratorNextID(ValkeyModuleKey *key,
ValkeyModuleStreamID *id,
long *numfields);
可用版本 6.2.0
查找下一个流条目并返回其流 ID 和字段数。
key
:已使用ValkeyModule_StreamIteratorStart()
启动流迭代器的键。id
:返回的流 ID。如果您不关心,则为 NULL。numfields
:找到的流条目中的字段数。如果您不关心,则为 NULL。
如果找到条目,则返回 VALKEYMODULE_OK
并设置 *id
和 *numfields
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时 key 为 NULL,则为 EINVAL
- 如果键引用了除流之外的其他类型的值或键为空,则为 ENOTSUP
- 如果没有流迭代器与键关联,则为 EBADF
- 如果迭代器范围内没有更多条目,则为 ENOENT
实际上,如果在成功调用 ValkeyModule_StreamIteratorStart()
后并使用相同的键调用 ValkeyModule_StreamIteratorNextID()
,则可以安全地假定 VALKEYMODULE_ERR
返回值表示没有更多条目。
使用 ValkeyModule_StreamIteratorNextField()
检索字段和值。请参阅 ValkeyModule_StreamIteratorStart()
处的示例。
ValkeyModule_StreamIteratorNextField
int ValkeyModule_StreamIteratorNextField(ValkeyModuleKey *key,
ValkeyModuleString **field_ptr,
ValkeyModuleString **value_ptr);
可用版本 6.2.0
在流迭代中检索当前流 ID 的下一个字段及其对应的值。在调用 ValkeyModule_StreamIteratorNextID()
之后应重复调用此函数以获取每个字段-值对。
key
:已启动流迭代器的键。field_ptr
:此处返回字段。value_ptr
:此处返回值。
返回 VALKEYMODULE_OK
并将 *field_ptr
和 *value_ptr
指向新分配的 ValkeyModuleString
对象。如果启用了自动内存,则字符串对象在回调完成时自动释放。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果调用时 key 为 NULL,则为 EINVAL
- 如果键引用了除流之外的其他类型的值或键为空,则为 ENOTSUP
- 如果没有流迭代器与键关联,则为 EBADF
- 如果当前流条目中没有更多字段,则为 ENOENT
实际上,如果在成功调用 ValkeyModule_StreamIteratorNextID()
后并使用相同的键调用 ValkeyModule_StreamIteratorNextField()
,则可以安全地假定 VALKEYMODULE_ERR
返回值表示没有更多字段。
请参阅 ValkeyModule_StreamIteratorStart()
处的示例。
ValkeyModule_StreamIteratorDelete
int ValkeyModule_StreamIteratorDelete(ValkeyModuleKey *key);
可用版本 6.2.0
在迭代时删除当前流条目。
此函数可在调用 ValkeyModule_StreamIteratorNextID()
之后或在任何对 ValkeyModule_StreamIteratorNextField()
的调用之后调用。
成功时返回 VALKEYMODULE_OK
。失败时,返回 VALKEYMODULE_ERR
并按如下设置 errno
- 如果 key 为 NULL,则为 EINVAL
- 如果键为空或为流以外的其他类型,则为 ENOTSUP
- 如果键未打开用于写入,或未启动迭代器,则为 EBADF
- 如果迭代器没有当前流条目,则为 ENOENT
ValkeyModule_StreamTrimByLength
long long ValkeyModule_StreamTrimByLength(ValkeyModuleKey *key,
int flags,
long long length);
可用版本 6.2.0
按长度修剪流,类似于带有 MAXLEN 的 XTRIM。
key
:打开用于写入的键。flags
:一个位字段,包含VALKEYMODULE_STREAM_TRIM_APPROX
:如果能提高性能,则减少修剪量,类似于带有~
的 XTRIM。
length
:修剪后要保留的流条目数。
返回已删除的条目数。失败时,返回负值并按如下设置 errno
- 如果调用时参数无效,则为 EINVAL
- 如果键为空或为流以外的其他类型,则为 ENOTSUP
- 如果键未打开用于写入,则为 EBADF
ValkeyModule_StreamTrimByID
long long ValkeyModule_StreamTrimByID(ValkeyModuleKey *key,
int flags,
ValkeyModuleStreamID *id);
可用版本 6.2.0
按 ID 修剪流,类似于带有 MINID 的 XTRIM。
key
:打开用于写入的键。flags
:一个位字段,包含VALKEYMODULE_STREAM_TRIM_APPROX
:如果能提高性能,则减少修剪量,类似于带有~
的 XTRIM。
id
:修剪后要保留的最小流 ID。
返回已删除的条目数。失败时,返回负值并按如下设置 errno
- 如果调用时参数无效,则为 EINVAL
- 如果键为空或为流以外的其他类型,则为 ENOTSUP
- 如果键未打开用于写入,则为 EBADF
从模块调用命令
ValkeyModule_Call()
将命令发送到服务器。其余函数处理回复。
ValkeyModule_FreeCallReply
void ValkeyModule_FreeCallReply(ValkeyModuleCallReply *reply);
可用版本 4.0.0
释放 Call 回复以及它包含的所有嵌套回复(如果它是数组)。
ValkeyModule_CallReplyType
int ValkeyModule_CallReplyType(ValkeyModuleCallReply *reply);
可用版本 4.0.0
将回复类型返回为以下之一
VALKEYMODULE_REPLY_UNKNOWN
VALKEYMODULE_REPLY_STRING
VALKEYMODULE_REPLY_ERROR
VALKEYMODULE_REPLY_INTEGER
VALKEYMODULE_REPLY_ARRAY
VALKEYMODULE_REPLY_NULL
VALKEYMODULE_REPLY_MAP
VALKEYMODULE_REPLY_SET
VALKEYMODULE_REPLY_BOOL
VALKEYMODULE_REPLY_DOUBLE
VALKEYMODULE_REPLY_BIG_NUMBER
VALKEYMODULE_REPLY_VERBATIM_STRING
VALKEYMODULE_REPLY_ATTRIBUTE
VALKEYMODULE_REPLY_PROMISE
ValkeyModule_CallReplyLength
size_t ValkeyModule_CallReplyLength(ValkeyModuleCallReply *reply);
可用版本 4.0.0
返回回复类型的长度(如果适用)。
ValkeyModule_CallReplyArrayElement
ValkeyModuleCallReply *ValkeyModule_CallReplyArrayElement(ValkeyModuleCallReply *reply,
size_t idx);
可用版本 4.0.0
返回数组回复的第 'idx' 个嵌套调用回复元素,如果回复类型错误或索引超出范围,则返回 NULL。
ValkeyModule_CallReplyInteger
long long ValkeyModule_CallReplyInteger(ValkeyModuleCallReply *reply);
可用版本 4.0.0
返回整数回复的 long long
值。
ValkeyModule_CallReplyDouble
double ValkeyModule_CallReplyDouble(ValkeyModuleCallReply *reply);
可用版本 7.0.0
返回双精度回复的双精度值。
ValkeyModule_CallReplyBigNumber
const char *ValkeyModule_CallReplyBigNumber(ValkeyModuleCallReply *reply,
size_t *len);
可用版本 7.0.0
返回大数回复的大数值。
ValkeyModule_CallReplyVerbatim
const char *ValkeyModule_CallReplyVerbatim(ValkeyModuleCallReply *reply,
size_t *len,
const char **format);
可用版本 7.0.0
返回逐字字符串回复的值。可以提供一个可选的输出参数来获取逐字回复格式。
ValkeyModule_CallReplyBool
int ValkeyModule_CallReplyBool(ValkeyModuleCallReply *reply);
可用版本 7.0.0
返回布尔回复的布尔值。
ValkeyModule_CallReplySetElement
ValkeyModuleCallReply *ValkeyModule_CallReplySetElement(ValkeyModuleCallReply *reply,
size_t idx);
可用版本 7.0.0
返回集合回复的第 'idx' 个嵌套调用回复元素,如果回复类型错误或索引超出范围,则返回 NULL。
ValkeyModule_CallReplyMapElement
int ValkeyModule_CallReplyMapElement(ValkeyModuleCallReply *reply,
size_t idx,
ValkeyModuleCallReply **key,
ValkeyModuleCallReply **val);
可用版本 7.0.0
检索映射回复的第 'idx' 个键和值。
返回
- 成功时返回
VALKEYMODULE_OK
。 - 如果 idx 超出范围或回复类型错误,则为
VALKEYMODULE_ERR
。
key
和 value
参数用于通过引用返回,如果不需要,可以为 NULL。
ValkeyModule_CallReplyAttribute
ValkeyModuleCallReply *ValkeyModule_CallReplyAttribute(ValkeyModuleCallReply *reply);
可用版本 7.0.0
返回给定回复的属性,如果不存在属性则返回 NULL。
ValkeyModule_CallReplyAttributeElement
int ValkeyModule_CallReplyAttributeElement(ValkeyModuleCallReply *reply,
size_t idx,
ValkeyModuleCallReply **key,
ValkeyModuleCallReply **val);
可用版本 7.0.0
检索属性回复的第 'idx' 个键和值。
返回
- 成功时返回
VALKEYMODULE_OK
。 - 如果 idx 超出范围或回复类型错误,则为
VALKEYMODULE_ERR
。
key
和 value
参数用于通过引用返回,如果不需要,可以为 NULL。
ValkeyModule_CallReplyPromiseSetUnblockHandler
void ValkeyModule_CallReplyPromiseSetUnblockHandler(ValkeyModuleCallReply *reply,
ValkeyModuleOnUnblocked on_unblock,
void *private_data);
可用版本 7.2.0
在给定的 promise ValkeyModuleCallReply
上设置解除阻塞处理程序(回调和私有数据)。给定的回复必须是 promise 类型(VALKEYMODULE_REPLY_PROMISE
)。
ValkeyModule_CallReplyPromiseAbort
int ValkeyModule_CallReplyPromiseAbort(ValkeyModuleCallReply *reply,
void **private_data);
可用版本 7.2.0
中止给定 promise ValkeyModuleCallReply
的执行。如果中止成功,则返回 REDMODULE_OK
;如果无法中止执行(执行已完成),则返回 VALKEYMODULE_ERR
。如果执行被中止(返回 REDMODULE_OK
),则 private_data
输出参数将设置为在“ValkeyModule_CallReplyPromiseSetUnblockHandler
”上给出的私有数据值,以便调用者能够释放私有数据。
如果执行成功中止,则承诺不会调用解除阻塞处理程序。也就是说,中止操作可能成功但操作仍将继续。例如,如果模块实现了一些阻塞命令并且不遵守断开连接回调,则可能会发生这种情况。对于服务器提供的命令,这种情况不会发生。
ValkeyModule_CallReplyStringPtr
const char *ValkeyModule_CallReplyStringPtr(ValkeyModuleCallReply *reply,
size_t *len);
可用版本 4.0.0
返回字符串或错误回复的指针和长度。
ValkeyModule_CreateStringFromCallReply
ValkeyModuleString *ValkeyModule_CreateStringFromCallReply(ValkeyModuleCallReply *reply);
可用版本 4.0.0
从类型为字符串、错误或整数的调用回复中返回一个新的字符串对象。否则(回复类型错误)返回 NULL。
ValkeyModule_SetContextUser
void ValkeyModule_SetContextUser(ValkeyModuleCtx *ctx,
const ValkeyModuleUser *user);
可用版本 7.0.6
修改 ValkeyModule_Call
将使用的用户(例如用于 ACL 检查)
ValkeyModule_Call
ValkeyModuleCallReply *ValkeyModule_Call(ValkeyModuleCtx *ctx,
const char *cmdname,
const char *fmt,
...);
可用版本 4.0.0
从模块调用任何命令的导出 API。
-
cmdname:要调用的命令。
-
fmt:命令参数的格式说明符字符串。每个参数都应由有效的类型规范指定。格式说明符还可以包含修饰符
!
、A
、3
和R
,它们没有对应的参数。-
b
-- 参数是缓冲区,紧随其后的是另一个参数,它是缓冲区的长度。 -
c
-- 参数是纯 C 字符串(以 null 结尾)的指针。 -
l
-- 参数是一个long long
整数。 -
s
-- 参数是一个 ValkeyModuleString。 -
v
-- 参数是 ValkeyModuleString 的向量。 -
!
-- 将命令及其参数发送到副本和 AOF。 -
A
-- 抑制 AOF 传播,仅发送到副本(需要!
)。 -
R
-- 抑制副本传播,仅发送到 AOF(需要!
)。 -
3
-- 返回 RESP3 回复。这将改变命令回复。例如,HGETALL 返回一个映射而不是扁平数组。 -
0
-- 以自动模式返回回复,即回复格式将与附加到给定 ValkeyModuleCtx 的客户端相同。这可能在您希望将回复直接传递给客户端时使用。 -
C
-- 作为附加到上下文的用户运行命令。用户要么通过直接发出命令并创建上下文的客户端自动附加,要么通过 ValkeyModule_SetContextUser 设置。如果上下文不是直接由发出的命令创建(例如后台上下文并且没有通过 ValkeyModule_SetContextUser 设置用户),则 ValkeyModule_Call 将失败。检查命令是否可以根据 ACL 规则执行,并导致命令作为确定的用户运行,以便任何将来的用户相关活动(例如脚本内的 ACL 检查)将按预期进行。否则,命令将作为无限制用户运行。 -
S
-- 在脚本模式下运行命令,这意味着如果调用了脚本中不允许的命令(带有deny-script
标志),它将引发错误(如 SHUTDOWN)。此外,在脚本模式下,如果副本数量不足(如min-replicas-to-write
配置),或者服务器无法持久化到磁盘,则不允许写入命令。 -
W
-- 不允许运行任何写入命令(带有write
标志)。 -
M
-- 超过内存限制时不允许deny-oom
标记的命令。 -
E
-- 以 ValkeyModuleCallReply 形式返回错误。如果在调用命令之前发生错误,则使用 errno 机制返回错误。此标志允许将错误也作为具有相关错误消息的错误 CallReply 获取。 -
'D' -- “空运行”模式。在执行底层 call() 之前返回。如果一切成功,它将返回 NULL,否则它将返回一个 CallReply 对象,表示错误,就像使用 'E' 代码调用一样。
-
'K' -- 允许运行阻塞命令。如果启用且命令被阻塞,将返回一个特殊的 VALKEYMODULE_REPLY_PROMISE。此回复类型表示命令被阻塞,回复将异步给出。模块可以使用此回复对象设置一个处理程序,当命令解除阻塞时,该处理程序将使用 ValkeyModule_CallReplyPromiseSetUnblockHandler 调用。处理程序必须在命令调用后立即设置(期间不释放锁)。如果未设置处理程序,阻塞命令仍将继续执行,但回复将被忽略(即发而忘之),请注意,在角色更改的情况下,这很危险,如下所述。模块可以使用 ValkeyModule_CallReplyPromiseAbort 中止命令调用(如果尚未完成)(有关详细信息,请参阅 ValkeyModule_CallReplyPromiseAbort 文档)。在角色更改时中止执行也是模块的责任,可以通过使用服务器事件(在实例成为副本时获得通知)或依赖原始客户端的断开连接回调。未能这样做可能导致在副本上进行写入操作。与其他调用回复不同,promise 调用回复必须在 GIL 锁定时释放。请注意,在解除阻塞时,唯一的承诺是解除阻塞处理程序将被调用,如果阻塞 ValkeyModule_Call 导致模块也阻塞了一些真实客户端(使用 ValkeyModule_BlockClient),则模块有责任在解除阻塞处理程序中解除阻塞此客户端。在解除阻塞处理程序中,只允许执行以下操作:* 使用 ValkeyModule_Call 调用附加命令 * 使用 ValkeyModule_OpenKey 打开键 * 将数据复制到副本或 AOF
Specifically, it is not allowed to call any module API which are client related such as: * ValkeyModule_Reply* API's * ValkeyModule_BlockClient * ValkeyModule_GetCurrentUserName
-
-
...:命令的实际参数。
成功时返回 ValkeyModuleCallReply
对象,否则返回 NULL 并将 errno 设置为以下值
- EBADF:格式说明符错误。
- EINVAL:命令参数数量错误。
- ENOENT:命令不存在。
- EPERM:群集实例中的操作,键位于非本地槽位。
- EROFS:群集实例中的操作,当在只读状态下发送写入命令时。
- ENETDOWN:群集实例中的操作,当群集已关闭时。
- ENOTSUP:指定的模块上下文没有 ACL 用户
- EACCES:根据 ACL 规则,命令无法执行
- ENOSPC:不允许写入或 deny-oom 命令
- ESPIPE:脚本模式下不允许命令
示例代码片段
reply = ValkeyModule_Call(ctx,"INCRBY","sc",argv[1],"10");
if (ValkeyModule_CallReplyType(reply) == VALKEYMODULE_REPLY_INTEGER) {
long long myval = ValkeyModule_CallReplyInteger(reply);
// Do something with myval.
}
此 API 文档在此处:https://valkey.com.cn/topics/modules-intro
ValkeyModule_CallReplyProto
const char *ValkeyModule_CallReplyProto(ValkeyModuleCallReply *reply,
size_t *len);
可用版本 4.0.0
返回一个指针和长度,指向返回回复对象的命令所返回的协议。
模块数据类型
当字符串 DMA 或使用现有数据结构不足时,可以从头开始创建新的数据类型。模块必须提供一组回调函数来处理导出的新值(例如,为了提供 RDB 保存/加载、AOF 重写等)。本节定义此 API。
ValkeyModule_CreateDataType
moduleType *ValkeyModule_CreateDataType(ValkeyModuleCtx *ctx,
const char *name,
int encver,
void *typemethods_ptr);
可用版本 4.0.0
注册模块导出的新数据类型。参数如下。有关深入文档,请查看模块 API 文档,特别是 https://valkey.com.cn/topics/modules-native-types。
-
name:一个 9 个字符的数据类型名称,在模块生态系统中必须是唯一的。发挥创意...就不会有冲突。使用字符集 A-Z a-z 9-0,加上两个 "-_" 字符。一个好主意是使用,例如
<typename>-<vendor>
。例如 "tree-AntZ" 可能表示 "@antirez 的树数据结构"。同时使用小写和大写字母有助于防止冲突。 -
encver:编码版本,即模块用于持久化数据的序列化版本。只要 "name" 匹配,RDB 加载就会调度到类型回调,无论使用何种 'encver',但是模块可以理解它必须加载的编码是否是模块的旧版本。例如,模块 "tree-AntZ" 最初使用 encver=0。后来升级后,它开始以不同格式序列化数据并使用 encver=1 注册类型。但是,如果
rdb_load
回调能够检查 encver 值并采取相应操作,则此模块仍可能加载旧版本生成的老数据。encver 必须是 0 到 1023 之间的正值。 -
typemethods_ptr 是一个指向
ValkeyModuleTypeMethods
结构的指针,应填充方法回调和结构版本,如下例所示ValkeyModuleTypeMethods tm = { .version = VALKEYMODULE_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' 参数是
VALKEYMODULE_AUX_BEFORE_RDB
或VALKEYMODULE_AUX_AFTER_RDB
。 -
aux_load:一个从 RDB 文件加载键空间外数据的回调函数指针。类似于
aux_save
,成功时返回VALKEYMODULE_OK
,否则返回 ERR。 -
free_effort:一个回调函数指针,用于确定模块的内存是否需要延迟回收。模块应返回释放值所涉及的复杂性。例如:将释放多少个指针。请注意,如果它返回 0,我们将始终进行异步释放。
-
unlink:一个回调函数指针,用于通知模块键已从 DB 中删除,并且可能很快会被后台线程释放。请注意,它不会在 FLUSHALL/FLUSHDB(同步和异步)上调用,模块可以使用
ValkeyModuleEvent_FlushDB
来挂钩。 -
copy:一个回调函数指针,用于复制指定键。模块应执行指定值的深拷贝并返回。此外,还提供了有关源键和目标键名称的提示。NULL 返回值被视为错误,复制操作失败。注意:如果目标键存在并被覆盖,将首先调用 copy 回调,然后调用 free 回调以释放正在替换的值。
-
defrag:一个回调函数指针,用于请求模块对键进行碎片整理。然后,模块应迭代指针并调用相关的
ValkeyModule_Defrag*()
函数来对指针或复杂类型进行碎片整理。模块应继续迭代,只要ValkeyModule_DefragShouldStop()
返回零值,并在完成时返回零值,如果还有更多工作要做,则返回非零值。如果需要更多工作,可以使用ValkeyModule_DefragCursorSet()
和ValkeyModule_DefragCursorGet()
来跟踪跨不同调用的工作。通常,碎片整理机制会在没有时间限制的情况下调用回调,因此ValkeyModule_DefragShouldStop()
总是返回零。“延迟碎片整理”机制具有时间限制并提供游标支持,仅用于确定具有显著内部复杂性的键。为此,碎片整理机制使用free_effort
回调和 'active-defrag-max-scan-fields' 配置指令。注意:该值作为void**
传递,如果顶级值指针被碎片整理并因此发生更改,函数应更新指针。 -
mem_usage2:与
mem_usage
类似,但提供了ValkeyModuleKeyOptCtx
参数,以便可以获取元信息(如键名和 db ID),以及用于大小估算的sample_size
(参见 MEMORY USAGE 命令)。 -
free_effort2:与
free_effort
类似,但提供了ValkeyModuleKeyOptCtx
参数,以便可以获取元信息(如键名和 db ID)。 -
unlink2:与
unlink
类似,但提供了ValkeyModuleKeyOptCtx
参数,以便可以获取元信息(如键名和 db ID)。 -
copy2:与
copy
类似,但提供了ValkeyModuleKeyOptCtx
参数,以便可以获取元信息(如键名和 db ID)。 -
aux_save2:与
aux_save
类似,但语义略有变化,如果模块在此回调中不保存任何内容,则不会将此辅助字段的任何数据写入 RDB,即使未加载模块也可以加载 RDB。
注意:模块名称 "AAAAAAAAA" 是保留的,并会产生错误,它也很糟糕。
如果 ValkeyModule_CreateDataType()
在 ValkeyModule_OnLoad()
函数之外被调用,或者已经有一个模块使用相同的名称注册了一个类型,或者模块名称或 encver 无效,则返回 NULL。否则,新类型将注册到服务器中,并返回一个类型为 ValkeyModuleType
的引用:函数的调用者应将此引用存储到全局变量中,以便将来在模块类型 API 中使用它,因为单个模块可以注册多种类型。示例代码片段
static ValkeyModuleType *BalancedTreeType;
int ValkeyModule_OnLoad(ValkeyModuleCtx *ctx) {
// some code here ...
BalancedTreeType = ValkeyModule_CreateDataType(...);
}
ValkeyModule_ModuleTypeSetValue
int ValkeyModule_ModuleTypeSetValue(ValkeyModuleKey *key,
moduleType *mt,
void *value);
可用版本 4.0.0
如果键已打开用于写入,则将指定的模块类型对象设置为键的值,如果存在旧值则删除。成功时返回 VALKEYMODULE_OK
。如果键未打开用于写入或存在活动迭代器,则返回 VALKEYMODULE_ERR
。
ValkeyModule_ModuleTypeGetType
moduleType *ValkeyModule_ModuleTypeGetType(ValkeyModuleKey *key);
可用版本 4.0.0
假设 ValkeyModule_KeyType()
在键上返回 VALKEYMODULE_KEYTYPE_MODULE
,则返回存储在键处的值的模块类型指针。
如果键为 NULL,未与模块类型关联,或为空,则返回 NULL。
ValkeyModule_ModuleTypeGetValue
void *ValkeyModule_ModuleTypeGetValue(ValkeyModuleKey *key);
可用版本 4.0.0
假设 ValkeyModule_KeyType()
在键上返回 VALKEYMODULE_KEYTYPE_MODULE
,则返回存储在键处的模块类型低级值,因为它是由用户通过 ValkeyModule_ModuleTypeSetValue()
设置的。
如果键为 NULL,未与模块类型关联,或为空,则返回 NULL。
RDB 加载和保存函数
ValkeyModule_IsIOError
int ValkeyModule_IsIOError(ValkeyModuleIO *io);
可用版本 6.0.0
如果任何先前的 IO API 失败,则返回 true。对于 Load*
API,必须首先使用 ValkeyModule_SetModuleOptions
设置 VALKEYMODULE_OPTIONS_HANDLE_IO_ERRORS
标志。
ValkeyModule_SaveUnsigned
void ValkeyModule_SaveUnsigned(ValkeyModuleIO *io, uint64_t value);
可用版本 4.0.0
将一个无符号 64 位值保存到 RDB 文件中。此函数只能在实现新数据类型的模块的 rdb_save
方法的上下文中调用。
ValkeyModule_LoadUnsigned
uint64_t ValkeyModule_LoadUnsigned(ValkeyModuleIO *io);
可用版本 4.0.0
从 RDB 文件加载一个无符号 64 位值。此函数只能在实现新数据类型的模块的 rdb_load
方法的上下文中调用。
ValkeyModule_SaveSigned
void ValkeyModule_SaveSigned(ValkeyModuleIO *io, int64_t value);
可用版本 4.0.0
与 ValkeyModule_SaveUnsigned()
类似,但用于有符号 64 位值。
ValkeyModule_LoadSigned
int64_t ValkeyModule_LoadSigned(ValkeyModuleIO *io);
可用版本 4.0.0
与 ValkeyModule_LoadUnsigned()
类似,但用于有符号 64 位值。
ValkeyModule_SaveString
void ValkeyModule_SaveString(ValkeyModuleIO *io, ValkeyModuleString *s);
可用版本 4.0.0
在模块类型 rdb_save
方法的上下文中,将一个字符串保存到 RDB 文件中,输入为 ValkeyModuleString
。
该字符串以后可以使用 ValkeyModule_LoadString()
或其他需要 RDB 文件中序列化字符串的 Load 系列函数加载。
ValkeyModule_SaveStringBuffer
void ValkeyModule_SaveStringBuffer(ValkeyModuleIO *io,
const char *str,
size_t len);
可用版本 4.0.0
与 ValkeyModule_SaveString()
类似,但接受原始 C 指针和长度作为输入。
ValkeyModule_LoadString
ValkeyModuleString *ValkeyModule_LoadString(ValkeyModuleIO *io);
可用版本 4.0.0
在模块数据类型 rdb_load
方法的上下文中,从 RDB 文件中加载一个字符串,该字符串之前已使用 ValkeyModule_SaveString()
函数系列保存。
返回的字符串是一个新分配的 ValkeyModuleString
对象,用户应在某个时候使用 ValkeyModule_FreeString()
调用释放它。
如果数据结构不将字符串存储为 ValkeyModuleString
对象,则可以使用类似的函数 ValkeyModule_LoadStringBuffer()
代替。
ValkeyModule_LoadStringBuffer
char *ValkeyModule_LoadStringBuffer(ValkeyModuleIO *io, size_t *lenptr);
可用版本 4.0.0
与 ValkeyModule_LoadString()
类似,但返回一个使用 ValkeyModule_Alloc()
分配的堆分配字符串,并且可以使用 ValkeyModule_Realloc()
或 ValkeyModule_Free()
调整大小或释放。
如果 '*lenptr' 不为 NULL,则字符串的大小存储在 '*lenptr' 中。返回的字符串不会自动以 NULL 终止,它会完全按照存储在 RDB 文件中的方式加载。
ValkeyModule_SaveDouble
void ValkeyModule_SaveDouble(ValkeyModuleIO *io, double value);
可用版本 4.0.0
在模块数据类型 rdb_save
方法的上下文中,将双精度值保存到 RDB 文件中。双精度值可以是有效数字、NaN 或无穷大。可以使用 ValkeyModule_LoadDouble()
加载回该值。
ValkeyModule_LoadDouble
double ValkeyModule_LoadDouble(ValkeyModuleIO *io);
可用版本 4.0.0
在模块数据类型 rdb_save
方法的上下文中,加载回由 ValkeyModule_SaveDouble()
保存的双精度值。
ValkeyModule_SaveFloat
void ValkeyModule_SaveFloat(ValkeyModuleIO *io, float value);
可用版本 4.0.0
在模块数据类型 rdb_save
方法的上下文中,将浮点值保存到 RDB 文件中。浮点值可以是有效数字、NaN 或无穷大。可以使用 ValkeyModule_LoadFloat()
加载回该值。
ValkeyModule_LoadFloat
float ValkeyModule_LoadFloat(ValkeyModuleIO *io);
可用版本 4.0.0
在模块数据类型 rdb_save
方法的上下文中,加载回由 ValkeyModule_SaveFloat()
保存的浮点值。
ValkeyModule_SaveLongDouble
void ValkeyModule_SaveLongDouble(ValkeyModuleIO *io, long double value);
可用版本 6.0.0
在模块数据类型 rdb_save
方法的上下文中,将长双精度值保存到 RDB 文件中。双精度值可以是有效数字、NaN 或无穷大。可以使用 ValkeyModule_LoadLongDouble()
加载回该值。
ValkeyModule_LoadLongDouble
long double ValkeyModule_LoadLongDouble(ValkeyModuleIO *io);
可用版本 6.0.0
在模块数据类型 rdb_save
方法的上下文中,加载回由 ValkeyModule_SaveLongDouble()
保存的长双精度值。
Key Digest API(用于模块类型的 DEBUG DIGEST 接口)
ValkeyModule_DigestAddStringBuffer
void ValkeyModule_DigestAddStringBuffer(ValkeyModuleDigest *md,
const char *ele,
size_t len);
可用版本 4.0.0
向摘要中添加一个新元素。此函数可以一次一个元素地多次调用,用于构成给定数据结构的所有元素。最终必须在添加了所有始终按给定顺序排列的元素后,调用 ValkeyModule_DigestEndSequence
。有关更多信息,请参阅模块数据类型文档。但是,这是一个使用 Set、Hash 和 List 数据类型作为示例的快速示例。
要添加一系列无序元素(例如在 Set 的情况下),要使用的模式是
foreach element {
AddElement(element);
EndSequence();
}
因为 Set 是无序的,所以添加的每个元素的位置都不依赖于其他元素。但是,如果我们的元素以对的形式有序,例如 Hash 的字段-值对,那么应该使用
foreach key,value {
AddElement(key);
AddElement(value);
EndSequence();
}
因为键和值将始终以上述顺序出现,而单个键-值对可以出现在哈希中的任何位置。
有序元素的列表将通过以下方式实现
foreach element {
AddElement(element);
}
EndSequence();
ValkeyModule_DigestAddLongLong
void ValkeyModule_DigestAddLongLong(ValkeyModuleDigest *md, long long ll);
可用版本 4.0.0
与 ValkeyModule_DigestAddStringBuffer()
类似,但接受 long long
作为输入,在将其添加到摘要之前将其转换为字符串。
ValkeyModule_DigestEndSequence
void ValkeyModule_DigestEndSequence(ValkeyModuleDigest *md);
可用版本 4.0.0
请参阅 ValkeyModule_DigestAddElement()
的文档。
ValkeyModule_LoadDataTypeFromStringEncver
void *ValkeyModule_LoadDataTypeFromStringEncver(const ValkeyModuleString *str,
const moduleType *mt,
int encver);
可用版本 7.0.0
从字符串 'str' 中解码模块数据类型 'mt' 的序列化表示,并指定编码版本 'encver',然后返回新分配的值,如果解码失败则返回 NULL。
此调用基本上重用了模块数据类型实现的 'rdb_load
' 回调,以允许模块任意序列化/反序列化键,类似于 'DUMP' 和 'RESTORE' 命令的实现方式。
模块通常应使用 VALKEYMODULE_OPTIONS_HANDLE_IO_ERRORS
标志,并确保反序列化代码正确检查和处理 IO 错误(释放分配的缓冲区并返回 NULL)。
如果未这样做,服务器将通过生成错误消息并终止进程来处理损坏(或只是截断)的序列化数据。
ValkeyModule_LoadDataTypeFromString
void *ValkeyModule_LoadDataTypeFromString(const ValkeyModuleString *str,
const moduleType *mt);
可用版本 6.0.0
类似于 ValkeyModule_LoadDataTypeFromStringEncver
,API 的原始版本,为向后兼容性保留。
ValkeyModule_SaveDataTypeToString
ValkeyModuleString *ValkeyModule_SaveDataTypeToString(ValkeyModuleCtx *ctx,
void *data,
const moduleType *mt);
可用版本 6.0.0
将模块数据类型 'mt' 值 'data' 编码为序列化形式,并将其作为新分配的 ValkeyModuleString
返回。
此调用基本上重用了模块数据类型实现的 'rdb_save
' 回调,以允许模块任意序列化/反序列化键,类似于 'DUMP' 和 'RESTORE' 命令的实现方式。
ValkeyModule_GetKeyNameFromDigest
const ValkeyModuleString *ValkeyModule_GetKeyNameFromDigest(ValkeyModuleDigest *dig);
可用版本 7.0.0
返回当前正在处理的键的名称。
ValkeyModule_GetDbIdFromDigest
int ValkeyModule_GetDbIdFromDigest(ValkeyModuleDigest *dig);
可用版本 7.0.0
返回当前正在处理的键的数据库 ID。
用于模块数据类型的 AOF API
ValkeyModule_EmitAOF
void ValkeyModule_EmitAOF(ValkeyModuleIO *io,
const char *cmdname,
const char *fmt,
...);
可用版本 4.0.0
在 AOF 重写过程中将命令发出到 AOF。此函数仅在模块导出的数据类型的 aof_rewrite
方法的上下文中调用。该命令在参数传递方式上与 ValkeyModule_Call()
完全相同,但它不返回任何内容,因为错误处理由服务器本身执行。
IO 上下文处理
ValkeyModule_GetKeyNameFromIO
const ValkeyModuleString *ValkeyModule_GetKeyNameFromIO(ValkeyModuleIO *io);
可用版本 5.0.5
返回当前正在处理的键的名称。不保证键名始终可用,因此此函数可能返回 NULL。
ValkeyModule_GetKeyNameFromModuleKey
const ValkeyModuleString *ValkeyModule_GetKeyNameFromModuleKey(ValkeyModuleKey *key);
可用版本 6.0.0
返回一个带有 ValkeyModuleKey
键名称的 ValkeyModuleString
。
ValkeyModule_GetDbIdFromModuleKey
int ValkeyModule_GetDbIdFromModuleKey(ValkeyModuleKey *key);
可用版本 7.0.0
返回 ValkeyModuleKey
的键的数据库 ID。
ValkeyModule_GetDbIdFromIO
int ValkeyModule_GetDbIdFromIO(ValkeyModuleIO *io);
可用版本 7.0.0
返回当前正在处理的键的数据库 ID。不保证此信息始终可用,因此可能返回 -1。
日志记录
ValkeyModule_Log
void ValkeyModule_Log(ValkeyModuleCtx *ctx,
const char *levelstr,
const char *fmt,
...);
可用版本 4.0.0
向标准服务器日志生成日志消息,格式接受类似 printf 的说明符,而 level 是一个描述发射日志时使用的日志级别的字符串,必须是以下之一
- "debug" (
VALKEYMODULE_LOGLEVEL_DEBUG
) - "verbose" (
VALKEYMODULE_LOGLEVEL_VERBOSE
) - "notice" (
VALKEYMODULE_LOGLEVEL_NOTICE
) - "warning" (
VALKEYMODULE_LOGLEVEL_WARNING
)
如果指定的日志级别无效,默认使用 verbose。此函数能够发出的日志行长度有固定限制,此限制未指定但保证超过几行文本。
如果调用者的上下文无法提供 ctx 参数(例如线程或回调),则 ctx 参数可以为 NULL,在这种情况下将使用通用的“模块”而不是模块名称。
ValkeyModule_LogIOError
void ValkeyModule_LogIOError(ValkeyModuleIO *io,
const char *levelstr,
const char *fmt,
...);
可用版本 4.0.0
记录 RDB / AOF 序列化回调中的错误。
当回调因某些关键原因无法加载或保存数据而向调用者返回关键错误时,应使用此函数。
ValkeyModule__Assert
void ValkeyModule__Assert(const char *estr, const char *file, int line);
可用版本 6.0.0
Valkey 断言函数。
建议使用宏 ValkeyModule_Assert(expression)
,而不是直接调用此函数。
断言失败将关闭服务器并生成与服务器本身生成的信息相同的日志信息。
ValkeyModule_LatencyAddSample
void ValkeyModule_LatencyAddSample(const char *event, mstime_t latency);
可用版本 6.0.0
允许向延迟监视器添加事件,以便由 LATENCY 命令观察。如果延迟小于配置的 latency-monitor-threshold,则跳过调用。
从模块阻塞客户端
有关模块中阻塞命令的指南,请参阅 https://valkey.com.cn/topics/modules-blocking-ops。
ValkeyModule_RegisterAuthCallback
void ValkeyModule_RegisterAuthCallback(ValkeyModuleCtx *ctx,
ValkeyModuleAuthCallback cb);
可用版本 7.2.0
此 API 注册一个回调函数,除了正常的基于密码的身份验证之外还会执行该函数。可以在不同模块之间注册多个回调函数。当模块卸载时,它注册的所有身份验证回调函数都将被注销。当调用 AUTH/HELLO 命令(提供 AUTH 字段)时,会尝试调用回调函数(按最新注册的顺序优先)。回调函数将以模块上下文以及用户名和密码的形式调用,并应采取以下操作之一:(1)身份验证 - 使用 ValkeyModule_AuthenticateClient
* API 并返回 VALKEYMODULE_AUTH_HANDLED
。这将立即结束身份验证链并成功添加 OK 回复。(2)拒绝身份验证 - 在不进行身份验证或阻塞客户端的情况下返回 VALKEYMODULE_AUTH_HANDLED
。可选地,可以将 err
设置为自定义错误消息,并且 err
将由服务器自动释放。这将立即结束身份验证链并失败添加 ERR 回复。(3)在身份验证时阻塞客户端 - 使用 ValkeyModule_BlockClientOnAuth
API 并返回 VALKEYMODULE_AUTH_HANDLED
。此时,客户端将被阻塞,直到使用 ValkeyModule_UnblockClient
API,这将触发身份验证回复回调(通过 ValkeyModule_BlockClientOnAuth
提供)。在此回复回调中,模块应进行身份验证、拒绝或跳过处理身份验证。(4)跳过处理身份验证 - 在不阻塞客户端的情况下返回 VALKEYMODULE_AUTH_NOT_HANDLED
。这将允许引擎尝试下一个模块身份验证回调。如果没有回调函数进行身份验证或拒绝身份验证,则尝试基于密码的身份验证,并将进行身份验证或添加失败日志并相应地回复客户端。
注意:如果客户端在阻塞模块身份验证期间断开连接,则 AUTH 或 HELLO 命令的该次发生将不会在 INFO 命令统计信息中跟踪。
以下是如何使用非阻塞模块身份验证的示例
int auth_cb(ValkeyModuleCtx *ctx, ValkeyModuleString *username, ValkeyModuleString *password, ValkeyModuleString
**err) { const char *user = ValkeyModule_StringPtrLen
(username, NULL); const char *pwd = ValkeyModule_StringPtrLen
(password, NULL); if (!strcmp(user,"foo") && !strcmp(pwd,"valid_password
")) { ValkeyModule_AuthenticateClientWithACLUser(ctx, "foo", 3, NULL, NULL, NULL); return VALKEYMODULE_AUTH_HANDLED; }
else if (!strcmp(user,"foo") && !strcmp(pwd,"wrong_password")) {
ValkeyModuleString *log = ValkeyModule_CreateString(ctx, "Module Auth", 11);
ValkeyModule_ACLAddLogEntryByUserName(ctx, username, log, VALKEYMODULE_ACL_LOG_AUTH);
ValkeyModule_FreeString(ctx, log);
const char *err_msg = "Auth denied by Misc Module.";
*err = ValkeyModule_CreateString(ctx, err_msg, strlen(err_msg));
return VALKEYMODULE_AUTH_HANDLED;
}
return VALKEYMODULE_AUTH_NOT_HANDLED;
}
int ValkeyModule_OnLoad(ValkeyModuleCtx *ctx, ValkeyModuleString **argv, int argc) {
if (ValkeyModule_Init(ctx,"authmodule",1,VALKEYMODULE_APIVER_1)== VALKEYMODULE_ERR)
return VALKEYMODULE_ERR;
ValkeyModule_RegisterAuthCallback(ctx, auth_cb);
return VALKEYMODULE_OK;
}
ValkeyModule_BlockClient
ValkeyModuleBlockedClient *ValkeyModule_BlockClient(ValkeyModuleCtx *ctx,
ValkeyModuleCmdFunc reply_callback,
ValkeyModuleCmdFunc timeout_callback,
void (*free_privdata)(ValkeyModuleCtx *, void *),
long long timeout_ms);
可用版本 4.0.0
在阻塞命令的上下文中阻塞客户端,返回一个句柄,该句柄稍后将用于通过调用 ValkeyModule_UnblockClient()
来解除阻塞客户端。参数指定回调函数和超时时间,超时后客户端将被解除阻塞。
回调函数在以下上下文中调用
reply_callback: called after a successful ValkeyModule_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 ValkeyModule_UnblockClient() call.
注意:ValkeyModule_UnblockClient
应该为每个被阻塞的客户端调用,即使客户端被终止、超时或断开连接。未能这样做将导致内存泄漏。
在某些情况下,无法使用 ValkeyModule_BlockClient()
- 如果客户端是 Lua 脚本。
- 如果客户端正在执行 MULTI 块。
在这些情况下,调用 ValkeyModule_BlockClient()
将不会阻塞客户端,而是产生特定的错误回复。
注册了 timeout_callback
函数的模块也可以使用 CLIENT UNBLOCK
命令解除阻塞,该命令将触发超时回调。如果未注册回调函数,则被阻塞的客户端将被视为未处于阻塞状态,并且 CLIENT UNBLOCK
将返回零值。
测量后台时间:默认情况下,阻塞命令中花费的时间不计入总命令持续时间。要包含此类时间,您应该在阻塞命令后台工作期间使用 ValkeyModule_BlockedClientMeasureTimeStart()
和 ValkeyModule_BlockedClientMeasureTimeEnd()
一次或多次。
ValkeyModule_BlockClientOnAuth
ValkeyModuleBlockedClient *ValkeyModule_BlockClientOnAuth(ValkeyModuleCtx *ctx,
ValkeyModuleAuthCallback reply_callback,
void (*free_privdata)(ValkeyModuleCtx *, void *));
可用版本 7.2.0
在后台阻塞当前客户端进行模块身份验证。如果客户端上没有正在进行的模块身份验证,则 API 返回 NULL。否则,客户端被阻塞,并返回 ValkeyModule_BlockedClient
,类似于 ValkeyModule_BlockClient
API。注意:仅在模块身份验证回调的上下文中使用此 API。
ValkeyModule_BlockClientGetPrivateData
void *ValkeyModule_BlockClientGetPrivateData(ValkeyModuleBlockedClient *blocked_client);
可用版本 7.2.0
获取之前在阻塞客户端上设置的私有数据
ValkeyModule_BlockClientSetPrivateData
void ValkeyModule_BlockClientSetPrivateData(ValkeyModuleBlockedClient *blocked_client,
void *private_data);
可用版本 7.2.0
在阻塞客户端上设置私有数据
ValkeyModule_BlockClientOnKeys
ValkeyModuleBlockedClient *ValkeyModule_BlockClientOnKeys(ValkeyModuleCtx *ctx,
ValkeyModuleCmdFunc reply_callback,
ValkeyModuleCmdFunc timeout_callback,
void (*free_privdata)(ValkeyModuleCtx *, void *),
long long timeout_ms,
ValkeyModuleString **keys,
int numkeys,
void *privdata);
可用版本 6.0.0
此调用类似于 ValkeyModule_BlockClient()
,但在这种情况下,我们不仅阻塞客户端,还要求服务器在某些键“准备就绪”时自动解除阻塞,即包含更多数据。
这基本上类似于典型的命令通常所做的事情,例如 BLPOP 或 BZPOPMAX:如果客户端不能立即提供服务,它就会被阻塞,然后当键接收到新数据(例如列表推送)时,客户端被解除阻塞并提供服务。
然而,在这种模块 API 的情况下,客户端何时解除阻塞?
- 如果您阻塞了一个具有关联阻塞操作的键(例如列表、有序集合、流等),则当相关键被通常解除该类型原生阻塞操作的操作(例如列表推送)定位时,客户端可能会解除阻塞。因此,如果我们在列表键上阻塞,RPUSH 命令可能会解除我们的客户端,依此类推。
- 如果您正在实现您的原生数据类型,或者您想添加除“1”之外的新解除阻塞条件,您可以调用模块 API
ValkeyModule_SignalKeyAsReady()
。
无论如何,我们不能确定客户端是否应该仅仅因为键被标记为就绪而解除阻塞:例如,后续操作可能会更改键,或者在此之前的队列中的客户端可能会被服务,从而再次修改键并使其为空。因此,当客户端被 ValkeyModule_BlockClientOnKeys()
阻塞时,回复回调不会在调用 ValkeyModule_UnblockClient()
之后调用,而是在每次键被标记为就绪时调用:如果回复回调可以服务客户端,它返回 VALKEYMODULE_OK
并且客户端被解除阻塞,否则它将返回 VALKEYMODULE_ERR
并且我们将稍后重试。
回复回调可以通过调用 API ValkeyModule_GetBlockedClientReadyKey()
访问被标记为就绪的键,该 API 仅返回键的字符串名称作为 ValkeyModuleString
对象。
得益于此系统,我们可以设置复杂的阻塞场景,例如仅当列表包含至少 5 个项或其他更复杂的逻辑时才解除阻塞客户端。
请注意,与 ValkeyModule_BlockClient()
的另一个区别是,我们在这里直接在阻塞客户端时传递私有数据:它将在回复回调中稍后可访问。通常,当使用 ValkeyModule_BlockClient()
阻塞时,用于回复客户端的私有数据在调用 ValkeyModule_UnblockClient()
时传递,但在这里,解除阻塞是由服务器本身执行的,因此我们需要事先准备一些私有数据。私有数据用于存储有关您正在实现的特定解除阻塞操作的任何信息。此类信息将使用用户提供的 free_privdata
回调释放。
然而,回复回调将能够访问命令的参数向量,因此通常不需要私有数据。
注意:在正常情况下,不应为被键阻塞的客户端调用 ValkeyModule_UnblockClient
(键要么就绪,要么会发生超时)。如果出于某种原因您确实想调用 ValkeyModule_UnblockClient,则可以:客户端将被视为超时(在这种情况下您必须实现超时回调)。
ValkeyModule_BlockClientOnKeysWithFlags
ValkeyModuleBlockedClient *ValkeyModule_BlockClientOnKeysWithFlags(ValkeyModuleCtx *ctx,
ValkeyModuleCmdFunc reply_callback,
ValkeyModuleCmdFunc timeout_callback,
void (*free_privdata)(ValkeyModuleCtx *, void *),
long long timeout_ms,
ValkeyModuleString **keys,
int numkeys,
void *privdata,
int flags);
可用版本 7.2.0
与 ValkeyModule_BlockClientOnKeys
相同,但可以采用 VALKEYMODULE_BLOCK_
* 标志。可以是 VALKEYMODULE_BLOCK_UNBLOCK_DEFAULT
,表示默认行为(与调用 ValkeyModule_BlockClientOnKeys
相同)
标志是一个位掩码,包含以下内容
VALKEYMODULE_BLOCK_UNBLOCK_DELETED
:如果任何keys
被删除,客户端应被唤醒。主要用于需要键存在的命令(如 XREADGROUP)
ValkeyModule_SignalKeyAsReady
void ValkeyModule_SignalKeyAsReady(ValkeyModuleCtx *ctx,
ValkeyModuleString *key);
可用版本 6.0.0
此函数用于可能解除被 ValkeyModule_BlockClientOnKeys()
阻塞的客户端。当调用此函数时,所有被此键阻塞的客户端都将调用其 reply_callback
。
ValkeyModule_UnblockClient
int ValkeyModule_UnblockClient(ValkeyModuleBlockedClient *bc, void *privdata);
可用版本 4.0.0
解除被 ValkeyModule_BlockedClient
阻塞的客户端。这将触发调用回复回调以回复客户端。'privdata' 参数将可由回复回调访问,因此此函数的调用者可以传递任何所需的值以实际回复客户端。
'privdata' 的常见用途是计算需要传递给客户端的线程,包括但不限于一些计算缓慢的回复或通过网络获得的回复。
注意 1:此函数可以由模块生成的线程调用。
注意 2:当我们使用 API ValkeyModule_BlockClientOnKeys()
解除阻塞被键阻塞的客户端时,这里的 privdata 参数未使用。使用此 API 解除阻塞被键阻塞的客户端仍将需要客户端获得一些回复,因此函数将使用“超时”处理程序来完成此操作(ValkeyModule_BlockClientOnKeys()
中提供的 privdata 可通过 ValkeyModule_GetBlockedClientPrivateData
从超时回调中访问)。
ValkeyModule_AbortBlock
int ValkeyModule_AbortBlock(ValkeyModuleBlockedClient *bc);
可用版本 4.0.0
中止阻塞客户端的阻塞操作:客户端将解除阻塞,不触发任何回调。
ValkeyModule_SetDisconnectCallback
void ValkeyModule_SetDisconnectCallback(ValkeyModuleBlockedClient *bc,
ValkeyModuleDisconnectFunc callback);
可用版本 5.0.0
设置一个回调函数,当阻塞客户端在模块有机会调用 ValkeyModule_UnblockClient()
之前断开连接时,将调用该函数。
通常,您需要做的是清理模块状态,以便可以安全地调用 ValkeyModule_UnblockClient()
,否则如果超时时间很长,客户端将永远保持阻塞状态。
注意事项
-
在此处调用 Reply* 系列函数是不安全的,也是无用的,因为客户端已消失。
-
如果客户端因超时而断开连接,则不会调用此回调。在这种情况下,客户端会自动解除阻塞,并调用超时回调。
ValkeyModule_IsBlockedReplyRequest
int ValkeyModule_IsBlockedReplyRequest(ValkeyModuleCtx *ctx);
可用版本 4.0.0
如果为了填充阻塞客户端的回复而调用了模块命令,则返回非零值。
ValkeyModule_IsBlockedTimeoutRequest
int ValkeyModule_IsBlockedTimeoutRequest(ValkeyModuleCtx *ctx);
可用版本 4.0.0
如果为了填充超时的阻塞客户端的回复而调用了模块命令,则返回非零值。
ValkeyModule_GetBlockedClientPrivateData
void *ValkeyModule_GetBlockedClientPrivateData(ValkeyModuleCtx *ctx);
可用版本 4.0.0
获取由 ValkeyModule_UnblockClient()
设置的私有数据
ValkeyModule_GetBlockedClientReadyKey
ValkeyModuleString *ValkeyModule_GetBlockedClientReadyKey(ValkeyModuleCtx *ctx);
可用版本 6.0.0
当回复回调在被 ValkeyModule_BlockClientOnKeys()
阻塞的客户端上下文中调用时,获取就绪的键。
ValkeyModule_GetBlockedClientHandle
ValkeyModuleBlockedClient *ValkeyModule_GetBlockedClientHandle(ValkeyModuleCtx *ctx);
可用版本 5.0.0
获取与给定上下文关联的阻塞客户端。这在阻塞客户端的回复和超时回调中很有用,有时模块具有阻塞客户端句柄引用,并希望清理它。
ValkeyModule_BlockedClientDisconnected
int ValkeyModule_BlockedClientDisconnected(ValkeyModuleCtx *ctx);
可用版本 5.0.0
如果调用阻塞客户端的自由回调时,客户端解除阻塞的原因是它在阻塞期间断开连接,则返回 true。
线程安全上下文
ValkeyModule_GetThreadSafeContext
ValkeyModuleCtx *ValkeyModule_GetThreadSafeContext(ValkeyModuleBlockedClient *bc);
可用版本 4.0.0
返回一个可在线程内部使用的上下文,用于使用某些模块 API 进行需要上下文的调用。如果 'bc' 不为 NULL,则模块将绑定到阻塞客户端,并且可以使用 ValkeyModule_Reply*
系列函数累积回复,以便在客户端解除阻塞时使用。否则,线程安全上下文将与特定客户端分离。
要调用非回复 API,必须使用以下命令准备线程安全上下文
ValkeyModule_ThreadSafeContextLock(ctx);
... make your call here ...
ValkeyModule_ThreadSafeContextUnlock(ctx);
当使用 ValkeyModule_Reply*
函数时,如果上下文是在使用阻塞客户端时创建的,则不需要此操作,否则根本不应进行任何 ValkeyModule_Reply*
调用。
注意:如果您正在创建分离的线程安全上下文(bc 为 NULL),请考虑使用 ValkeyModule_GetDetachedThreadSafeContext
,它还将保留模块 ID,因此对日志记录更有用。
ValkeyModule_GetDetachedThreadSafeContext
ValkeyModuleCtx *ValkeyModule_GetDetachedThreadSafeContext(ValkeyModuleCtx *ctx);
可用版本 6.0.9
返回一个分离的线程安全上下文,它不与任何特定的阻塞客户端关联,但与模块的上下文关联。
这对于希望长期持有全局上下文以进行日志记录等目的的模块非常有用。
ValkeyModule_FreeThreadSafeContext
void ValkeyModule_FreeThreadSafeContext(ValkeyModuleCtx *ctx);
可用版本 4.0.0
释放一个线程安全上下文。
ValkeyModule_ThreadSafeContextLock
void ValkeyModule_ThreadSafeContextLock(ValkeyModuleCtx *ctx);
可用版本 4.0.0
在执行线程安全 API 调用之前获取服务器锁。当有阻塞客户端连接到线程安全上下文时,ValkeyModule_Reply*
调用不需要此操作。
ValkeyModule_ThreadSafeContextTryLock
int ValkeyModule_ThreadSafeContextTryLock(ValkeyModuleCtx *ctx);
可用版本 6.0.8
类似于 ValkeyModule_ThreadSafeContextLock
,但如果服务器锁已被获取,此函数不会阻塞。
如果成功(锁已获取),返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno。
ValkeyModule_ThreadSafeContextUnlock
void ValkeyModule_ThreadSafeContextUnlock(ValkeyModuleCtx *ctx);
可用版本 4.0.0
执行线程安全 API 调用后释放服务器锁。
模块键空间通知 API
ValkeyModule_SubscribeToKeyspaceEvents
int ValkeyModule_SubscribeToKeyspaceEvents(ValkeyModuleCtx *ctx,
int types,
ValkeyModuleNotificationFunc callback);
可用版本 4.0.9
订阅键空间通知。这是键空间通知 API 的低级版本。模块可以注册回调以在发生键空间事件时收到通知。
通知事件按其类型(字符串事件、集合事件等)过滤,订阅者回调仅接收与特定事件类型掩码匹配的事件。
使用 ValkeyModule_SubscribeToKeyspaceEvents
订阅通知时,模块必须提供一个事件类型掩码,表示订阅者感兴趣的事件。这可以是以下任何标志的按位或组合:
VALKEYMODULE_NOTIFY_GENERIC
:通用命令,如 DEL、EXPIRE、RENAMEVALKEYMODULE_NOTIFY_STRING
:字符串事件VALKEYMODULE_NOTIFY_LIST
:列表事件VALKEYMODULE_NOTIFY_SET
:集合事件VALKEYMODULE_NOTIFY_HASH
:哈希事件VALKEYMODULE_NOTIFY_ZSET
:有序集合事件VALKEYMODULE_NOTIFY_EXPIRED
:过期事件VALKEYMODULE_NOTIFY_EVICTED
:逐出事件VALKEYMODULE_NOTIFY_STREAM
:流事件VALKEYMODULE_NOTIFY_MODULE
:模块类型事件VALKEYMODULE_NOTIFY_KEYMISS
:键丢失事件。请注意,键丢失事件是唯一在读取命令中触发的事件。在此通知中执行带有写入命令的 ValkeyModule_Call 是错误且不推荐的。它将导致触发事件的读取命令被复制到 AOF/副本。VALKEYMODULE_NOTIFY_ALL
:所有事件(不包括VALKEYMODULE_NOTIFY_KEYMISS
)VALKEYMODULE_NOTIFY_LOADED
:仅适用于模块的特殊通知,表示键已从持久化中加载。请注意,当此事件触发时,无法保留给定的键,请改用 ValkeyModule_CreateStringFromString。
我们不区分键事件和键空间事件,由模块根据键过滤采取的动作。
订阅者签名是:
int (*ValkeyModuleNotificationFunc) (ValkeyModuleCtx *ctx, int type,
const char *event,
ValkeyModuleString *key);
type
是事件类型位,必须与注册时给定的掩码匹配。事件字符串是实际执行的命令,而 key 是相关的键。
通知回调在不能用于向客户端发送任何内容的上下文中执行,并且其选定的数据库编号是事件发生的数据库编号。
请注意,对于模块通知而言,不需要在 valkey.conf 中启用通知即可工作。
警告:通知回调是同步执行的,因此通知回调必须快速,否则它们会降低服务器速度。如果您需要执行长时间操作,请使用线程将其卸载。
此外,通知同步执行的事实意味着通知代码将在服务器逻辑(命令逻辑、逐出、过期)的中间执行。在逻辑运行时更改键空间是危险且不鼓励的。为了对键空间事件做出写入操作响应,请参阅 ValkeyModule_AddPostNotificationJob
。
更多信息请参阅 https://valkey.com.cn/topics/notifications。
ValkeyModule_AddPostNotificationJob
int ValkeyModule_AddPostNotificationJob(ValkeyModuleCtx *ctx,
ValkeyModulePostNotificationJobFunc callback,
void *privdata,
void (*free_privdata)(void *));
可用版本 7.2.0
在键空间通知回调中运行时,执行任何写入操作都是危险且高度不推荐的(参见 ValkeyModule_SubscribeToKeyspaceEvents
)。为了在这种情况下仍然执行写入操作,服务器提供了 ValkeyModule_AddPostNotificationJob
API。该 API 允许注册一个作业回调,服务器将在以下条件得到满足时调用它:
- 可以安全地执行任何写入操作。
- 该作业将与键空间通知一起原子地调用。
请注意,一个作业可能会触发键空间通知,从而触发更多作业。这引发了进入无限循环的担忧,我们认为无限循环是模块中需要修复的逻辑错误,尝试通过停止执行来防止无限循环可能会导致功能正确性受到侵犯,因此服务器不会尝试保护模块免受无限循环的影响。
'free_pd
' 可以为 NULL,在这种情况下将不使用它。
成功时返回 VALKEYMODULE_OK
,如果在从磁盘加载数据(AOF 或 RDB)时调用或实例是只读副本,则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetNotifyKeyspaceEvents
int ValkeyModule_GetNotifyKeyspaceEvents(void);
可用版本 6.0.0
获取配置的 notify-keyspace-events 位图(可用于在 ValkeyModuleNotificationFunc
中进行额外过滤)
ValkeyModule_NotifyKeyspaceEvent
int ValkeyModule_NotifyKeyspaceEvent(ValkeyModuleCtx *ctx,
int type,
const char *event,
ValkeyModuleString *key);
可用版本 6.0.0
向模块公开 notifyKeyspaceEvent
模块集群 API
ValkeyModule_RegisterClusterMessageReceiver
void ValkeyModule_RegisterClusterMessageReceiver(ValkeyModuleCtx *ctx,
uint8_t type,
ValkeyModuleClusterMessageReceiver callback);
可用版本 5.0.0
注册类型为“type”的集群消息的回调接收器。如果已存在已注册的回调,这将用提供的新回调函数替换旧回调函数;否则,如果回调设置为 NULL 且该函数已存在回调,则取消注册回调(因此此 API 调用也用于删除接收器)。
当收到此类型的消息时,注册的回调函数将被调用,并提供详细信息,包括发送方的 40 字节节点 ID。
在 Valkey 8.1 及更高版本中,节点 ID 以 null 终止。在 8.1 之前,它不以 null 终止。
ValkeyModule_SendClusterMessage
int ValkeyModule_SendClusterMessage(ValkeyModuleCtx *ctx,
const char *target_id,
uint8_t type,
const char *msg,
uint32_t len);
可用版本 5.0.0
如果 target
为 NULL,则向集群中的所有节点发送消息;否则,发送到指定的 target,它是一个 VALKEYMODULE_NODE_ID_LEN
字节的节点 ID,由接收器回调或节点迭代函数返回。
在 Valkey 8.1 及更高版本中,此消息的集群协议开销约为 30B,而早期版本约为 2KB。
如果消息成功发送,函数返回 VALKEYMODULE_OK
;否则,如果节点未连接或该节点 ID 未映射到任何已知集群节点,则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetClusterNodesList
char **ValkeyModule_GetClusterNodesList(ValkeyModuleCtx *ctx,
size_t *numnodes);
可用版本 5.0.0
返回一个字符串指针数组,每个字符串指针指向一个正好是 VALKEYMODULE_NODE_ID_LEN
字节的集群节点 ID(不带任何 null 终止符)。返回的节点 ID 数量存储在 *numnodes
中。但是,如果此函数由未在启用集群的实例上运行的模块调用,则返回 NULL。
返回的 ID 可与 ValkeyModule_GetClusterNodeInfo()
一起使用,以获取有关单个节点的更多信息。
此函数返回的数组必须使用函数 ValkeyModule_FreeClusterNodesList()
释放。
示例
size_t count, j;
char **ids = ValkeyModule_GetClusterNodesList(ctx,&count);
for (j = 0; j < count; j++) {
ValkeyModule_Log(ctx,"notice","Node %.*s",
VALKEYMODULE_NODE_ID_LEN,ids[j]);
}
ValkeyModule_FreeClusterNodesList(ids);
ValkeyModule_FreeClusterNodesList
void ValkeyModule_FreeClusterNodesList(char **ids);
可用版本 5.0.0
释放使用 ValkeyModule_GetClusterNodesList
获取的节点列表。
ValkeyModule_GetMyClusterID
const char *ValkeyModule_GetMyClusterID(void);
可用版本 5.0.0
返回此节点 ID(VALKEYMODULE_CLUSTER_ID_LEN
字节),如果集群被禁用则返回 NULL。
ValkeyModule_GetClusterSize
size_t ValkeyModule_GetClusterSize(void);
可用版本 5.0.0
返回集群中的节点数量,无论其状态(握手、无地址等)如何,因此活动节点的数量可能实际更小,但不会大于此数量。如果实例未处于集群模式,则返回零。
ValkeyModule_GetClusterNodeInfo
int ValkeyModule_GetClusterNodeInfo(ValkeyModuleCtx *ctx,
const char *id,
char *ip,
char *primary_id,
int *port,
int *flags);
可用版本 5.0.0
填充 ID 为指定“id”的节点信息,然后返回 VALKEYMODULE_OK
。否则,如果节点 ID 格式无效或从本地域的角度来看节点 ID 不存在,则返回 VALKEYMODULE_ERR
。
如果不需要回填某些信息,参数 ip
、primary_id
、port
和 flags
可以为 NULL。如果指定了 ip
和 primary_id
(仅在实例是副本时填充),它们指向至少 VALKEYMODULE_NODE_ID_LEN
字节的缓冲区。作为 ip
和 primary_id
写回的字符串没有 null 终止符。
报告的标志列表如下:
VALKEYMODULE_NODE_MYSELF
:此节点VALKEYMODULE_NODE_PRIMARY
:节点是主节点VALKEYMODULE_NODE_REPLICA
:节点是副本VALKEYMODULE_NODE_PFAIL
:我们认为节点正在故障VALKEYMODULE_NODE_FAIL
:集群同意节点正在故障VALKEYMODULE_NODE_NOFAILOVER
:副本配置为永不故障转移
ValkeyModule_GetClusterNodeInfoForClient
int ValkeyModule_GetClusterNodeInfoForClient(ValkeyModuleCtx *ctx,;
可用版本 8.0.0
类似于 ValkeyModule_GetClusterNodeInfo()
,但根据客户端是通过 IPv4 还是 IPv6 连接,专门为给定客户端返回 IP 地址。
另请参阅 ValkeyModule_GetClientId()
。
ValkeyModule_SetClusterFlags
void ValkeyModule_SetClusterFlags(ValkeyModuleCtx *ctx, uint64_t flags);
可用版本 5.0.0
设置集群标志以更改集群的正常行为,特别是禁用某些功能。这对于使用集群 API 创建不同分布式系统但仍希望使用集群消息总线的模块很有用。可以设置的标志:
CLUSTER_MODULE_FLAG_NO_FAILOVER
CLUSTER_MODULE_FLAG_NO_REDIRECTION
具有以下效果:
-
NO_FAILOVER
:防止集群副本故障转移死主节点。还禁用副本迁移功能。 -
NO_REDIRECTION
:每个节点都将接受任何键,而不会尝试根据集群算法执行分区。槽位信息仍将在集群中传播,但无效。
ValkeyModule_ClusterKeySlot
unsigned int ValkeyModule_ClusterKeySlot(ValkeyModuleString *key);
可用版本 8.0.0
返回键的集群槽位,类似于 CLUSTER KEYSLOT
命令。即使未启用集群模式,此函数也有效。
ValkeyModule_ClusterCanonicalKeyNameInSlot
const char *ValkeyModule_ClusterCanonicalKeyNameInSlot(unsigned int slot);
可用版本 8.0.0
返回一个短字符串,可以用作键或键中的哈希标签,从而使键映射到给定的集群槽位。如果槽位不是有效槽位,则返回 NULL。
模块计时器 API
模块计时器是一种高精度的“绿色计时器”抽象,每个模块都可以注册数百万个计时器而不会出现问题,即使实际事件循环只有一个计时器用于唤醒模块计时器子系统以处理下一个事件。
所有计时器都存储在基数树中,按过期时间排序。当主服务器事件循环计时器回调被调用时,我们尝试依次处理所有已过期的计时器。然后我们重新进入事件循环,注册一个将在下一个待处理模块计时器过期时过期的计时器。
每当活动计时器列表降至零时,我们就会注销主事件循环计时器,这样当不使用此功能时就不会有开销。
ValkeyModule_CreateTimer
ValkeyModuleTimerID ValkeyModule_CreateTimer(ValkeyModuleCtx *ctx,
mstime_t period,
ValkeyModuleTimerProc callback,
void *data);
可用版本 5.0.0
创建一个新计时器,该计时器将在 period
毫秒后触发,并将使用 data
作为参数调用指定函数。返回的计时器 ID 可用于获取计时器信息或在触发前停止它。请注意,对于重复计时器的常见用例(在 ValkeyModuleTimerProc
回调中重新注册计时器),此 API 的调用时间很重要:如果在“回调”开始时调用,则表示事件将每“period”触发一次。如果在“回调”结束时调用,则表示事件之间会有“period”毫秒的间隔。(如果执行“回调”所需的时间可以忽略不计,则上述两个语句含义相同)
ValkeyModule_StopTimer
int ValkeyModule_StopTimer(ValkeyModuleCtx *ctx,
ValkeyModuleTimerID id,
void **data);
可用版本 5.0.0
停止一个计时器,如果找到计时器,它属于调用模块,并且已停止,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
。如果 data
指针不为 NULL,则在创建计时器时将其设置为 data
参数的值。
ValkeyModule_GetTimerInfo
int ValkeyModule_GetTimerInfo(ValkeyModuleCtx *ctx,
ValkeyModuleTimerID id,
uint64_t *remaining,
void **data);
可用版本 5.0.0
获取计时器信息:触发前的剩余时间(毫秒),以及与计时器关联的私有数据指针。如果指定的计时器不存在或属于不同的模块,则不返回任何信息,函数返回 VALKEYMODULE_ERR
,否则返回 VALKEYMODULE_OK
。如果调用者不需要某些信息,参数 remaining 或 data 可以为 NULL。
模块事件循环 API
ValkeyModule_EventLoopAdd
int ValkeyModule_EventLoopAdd(int fd,
int mask,
ValkeyModuleEventLoopFunc func,
void *user_data);
可用版本 7.0.0
将管道/套接字事件添加到事件循环。
-
mask
必须是以下值之一:VALKEYMODULE_EVENTLOOP_READABLE
VALKEYMODULE_EVENTLOOP_WRITABLE
VALKEYMODULE_EVENTLOOP_READABLE | VALKEYMODULE_EVENTLOOP_WRITABLE
成功时返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno:
- ERANGE:
fd
为负数或高于maxclients
服务器配置。 - 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);
}
ValkeyModule_EventLoopAdd(fd, VALKEYMODULE_EVENTLOOP_READABLE, onReadable, NULL);
ValkeyModule_EventLoopDel
int ValkeyModule_EventLoopDel(int fd, int mask);
可用版本 7.0.0
从事件循环中删除管道/套接字事件。
-
mask
必须是以下值之一:VALKEYMODULE_EVENTLOOP_READABLE
VALKEYMODULE_EVENTLOOP_WRITABLE
VALKEYMODULE_EVENTLOOP_READABLE | VALKEYMODULE_EVENTLOOP_WRITABLE
成功时返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno:
- ERANGE:
fd
为负数或高于maxclients
服务器配置。 - EINVAL:
mask
值无效。
ValkeyModule_EventLoopAddOneShot
int ValkeyModule_EventLoopAddOneShot(ValkeyModuleEventLoopOneShotFunc func,
void *user_data);
可用版本 7.0.0
此函数可以从其他线程调用,以在服务器主线程上触发回调。成功时返回 VALKEYMODULE_OK
。如果 func
为 NULL,则返回 VALKEYMODULE_ERR
并将 errno 设置为 EINVAL。
模块 ACL API
实现对服务器内部身份验证和授权的钩子。
ValkeyModule_CreateModuleUser
ValkeyModuleUser *ValkeyModule_CreateModuleUser(const char *name);
可用版本 6.0.0
创建一个 ACL 用户,模块可以使用该用户对客户端进行身份验证。获取用户后,模块应使用 ValkeyModule_SetUserACL()
函数设置该用户可以执行的操作。配置后,可以使用 ValkeyModule_AuthClientWithUser()
函数,通过指定的 ACL 规则对连接进行身份验证。
请注意:
- 此处创建的用户不会被 ACL 命令列出。
- 此处创建的用户不会检查重复名称,因此由调用此函数的模块负责不要创建同名用户。
- 创建的用户可用于验证多个连接。
调用者稍后可以使用函数 ValkeyModule_FreeModuleUser()
释放用户。当调用此函数时,如果仍有客户端使用此用户进行身份验证,它们将被断开连接。释放用户的函数只应在调用者真正希望使该用户失效以定义具有不同功能的新用户时使用。
ValkeyModule_FreeModuleUser
int ValkeyModule_FreeModuleUser(ValkeyModuleUser *user);
可用版本 6.0.0
释放给定用户并断开所有已使用该用户进行身份验证的客户端。有关详细用法,请参阅 ValkeyModule_CreateModuleUser
。
ValkeyModule_SetModuleUserACL
int ValkeyModule_SetModuleUserACL(ValkeyModuleUser *user, const char *acl);
可用版本 6.0.0
设置通过模块接口创建的用户权限。语法与 ACL SETUSER 相同,因此有关更多信息,请参阅 acl.c 中的文档。有关详细用法,请参阅 ValkeyModule_CreateModuleUser
。
成功时返回 VALKEYMODULE_OK
,失败时返回 VALKEYMODULE_ERR
并设置一个描述操作失败原因的 errno。
ValkeyModule_SetModuleUserACLString
int ValkeyModule_SetModuleUserACLString(ValkeyModuleCtx *ctx,
ValkeyModuleUser *user,
const char *acl,
ValkeyModuleString **error);
可用版本 7.0.6
使用完整的 ACL 字符串设置用户权限,就像在 ACL SETUSER 命令行 API 上使用一样。这与 ValkeyModule_SetModuleUserACL
不同,后者一次只接受单个 ACL 操作。
成功时返回 VALKEYMODULE_OK
,如果提供的 ValkeyModuleString
出错则返回 VALKEYMODULE_ERR
,并返回一个描述错误的字符串。
ValkeyModule_GetModuleUserACLString
ValkeyModuleString *ValkeyModule_GetModuleUserACLString(ValkeyModuleUser *user);
可用版本 7.0.6
获取给定用户的 ACL 字符串。返回一个 ValkeyModuleString
。
ValkeyModule_GetCurrentUserName
ValkeyModuleString *ValkeyModule_GetCurrentUserName(ValkeyModuleCtx *ctx);
可用版本 7.0.0
检索当前上下文后面的客户端连接的用户名。用户名稍后可用于获取 ValkeyModuleUser
。有关更多信息,请参阅 ValkeyModule_GetModuleUserFromUserName
。
返回的字符串必须使用 ValkeyModule_FreeString()
或通过启用自动内存管理来释放。
如果上下文未与客户端连接关联,则返回 NULL 并将 errno 设置为 EINVAL。
ValkeyModule_GetModuleUserFromUserName
ValkeyModuleUser *ValkeyModule_GetModuleUserFromUserName(ValkeyModuleString *name);
可用版本 7.0.0
ValkeyModuleUser
可用于根据与该用户关联的 ACL 规则检查命令、键或通道是否可以执行或访问。当模块希望对通用 ACL 用户(未由 ValkeyModule_CreateModuleUser
创建)执行 ACL 检查时,它可以根据由 ValkeyModule_GetCurrentUserName
检索到的用户名,通过此 API 获取 ValkeyModuleUser
。
由于通用 ACL 用户可以随时删除,此 ValkeyModuleUser
只能在此函数被调用的上下文中使用。为了在该上下文之外执行 ACL 检查,模块可以存储用户名,并在任何其他上下文调用此 API。
如果用户被禁用或用户不存在,则返回 NULL。调用者稍后应使用函数 ValkeyModule_FreeModuleUser()
释放用户。
ValkeyModule_ACLCheckCommandPermissions
int ValkeyModule_ACLCheckCommandPermissions(ValkeyModuleUser *user,
ValkeyModuleString **argv,
int argc);
可用版本 7.0.0
根据与用户关联的 ACL,检查用户是否可以执行该命令。
成功时返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno:
- ENOENT:指定命令不存在。
- EACCES:根据 ACL 规则,命令无法执行
ValkeyModule_ACLCheckKeyPermissions
int ValkeyModule_ACLCheckKeyPermissions(ValkeyModuleUser *user,
ValkeyModuleString *key,
int flags);
可用版本 7.0.0
根据附加到用户的 ACL 和表示键访问的标志,检查用户是否可以访问该键。这些标志与用于逻辑操作的键规范中使用的标志相同。这些标志在 ValkeyModule_SetCommandInfo
中作为 VALKEYMODULE_CMD_KEY_ACCESS
、VALKEYMODULE_CMD_KEY_UPDATE
、VALKEYMODULE_CMD_KEY_INSERT
和 VALKEYMODULE_CMD_KEY_DELETE
标志进行文档说明。
如果没有提供标志,则仍要求用户对该键具有某种访问权限,此命令才能成功返回。
如果用户能够访问该键,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并将 errno 设置为以下值之一:
- EINVAL:提供的标志无效。
- EACCESS:用户没有访问该键的权限。
ValkeyModule_ACLCheckChannelPermissions
int ValkeyModule_ACLCheckChannelPermissions(ValkeyModuleUser *user,
ValkeyModuleString *ch,
int flags);
可用版本 7.0.0
根据给定的访问标志检查用户是否可以访问 pubsub 通道。有关可以传入的可能标志的更多信息,请参阅 ValkeyModule_ChannelAtPosWithFlags
。
如果用户能够访问 pubsub 通道,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并将 errno 设置为以下值之一:
- EINVAL:提供的标志无效。
- EACCESS:用户没有访问 pubsub 通道的权限。
ValkeyModule_ACLAddLogEntry
int ValkeyModule_ACLAddLogEntry(ValkeyModuleCtx *ctx,
ValkeyModuleUser *user,
ValkeyModuleString *object,
ValkeyModuleACLLogEntryReason reason);
可用版本 7.0.0
在 ACL 日志中添加新条目。成功时返回 VALKEYMODULE_OK
,错误时返回 VALKEYMODULE_ERR
。
有关 ACL 日志的更多信息,请参阅 https://valkey.com.cn/commands/acl-log
ValkeyModule_ACLAddLogEntryByUserName
int ValkeyModule_ACLAddLogEntryByUserName(ValkeyModuleCtx *ctx,
ValkeyModuleString *username,
ValkeyModuleString *object,
ValkeyModuleACLLogEntryReason reason);
可用版本 7.2.0
使用提供的 username
ValkeyModuleString
在 ACL 日志中添加新条目。成功时返回 VALKEYMODULE_OK
,错误时返回 VALKEYMODULE_ERR
。
有关 ACL 日志的更多信息,请参阅 https://valkey.com.cn/commands/acl-log
ValkeyModule_AuthenticateClientWithUser
int ValkeyModule_AuthenticateClientWithUser(ValkeyModuleCtx *ctx,
ValkeyModuleUser *module_user,
ValkeyModuleUserChangedFunc callback,
void *privdata,
uint64_t *client_id);
可用版本 6.0.0
使用提供的 acl 用户对当前上下文的用户进行身份验证。如果用户被禁用,则返回 VALKEYMODULE_ERR
。
有关回调、client_id
和身份验证的通用用法的信息,请参阅 authenticateClientWithUser。
ValkeyModule_AuthenticateClientWithACLUser
int ValkeyModule_AuthenticateClientWithACLUser(ValkeyModuleCtx *ctx,
const char *name,
size_t len,
ValkeyModuleUserChangedFunc callback,
void *privdata,
uint64_t *client_id);
可用版本 6.0.0
使用提供的 acl 用户对当前上下文的用户进行身份验证。如果用户被禁用或用户不存在,则返回 VALKEYMODULE_ERR
。
有关回调、client_id
和身份验证的通用用法的信息,请参阅 authenticateClientWithUser。
ValkeyModule_DeauthenticateAndCloseClient
int ValkeyModule_DeauthenticateAndCloseClient(ValkeyModuleCtx *ctx,
uint64_t client_id);
可用版本 6.0.0
取消客户端身份验证并关闭客户端。客户端资源不会立即释放,但会在后台作业中清理。这是取消客户端身份验证的推荐方式,因为大多数客户端无法处理用户取消身份验证的情况。当客户端不存在时返回 VALKEYMODULE_ERR
,当操作成功时返回 VALKEYMODULE_OK
。
客户端 ID 由 ValkeyModule_AuthenticateClientWithUser
和 ValkeyModule_AuthenticateClientWithACLUser
API 返回,但可以通过 CLIENT API 或通过服务器事件获取。
此函数不是线程安全的,必须在命令或线程安全上下文的上下文中执行。
ValkeyModule_RedactClientCommandArgument
int ValkeyModule_RedactClientCommandArgument(ValkeyModuleCtx *ctx, int pos);
可用版本 7.0.0
编辑指定位置的客户端命令参数。编辑过的参数在面向用户的命令(如 SLOWLOG 或 MONITOR)中会被混淆,并且永远不会写入服务器日志。此命令可以在同一位置多次调用。
请注意,命令名称(位置 0)不能编辑。
如果参数已编辑,则返回 VALKEYMODULE_OK
;如果传入无效参数或位置超出客户端参数范围,则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetClientCertificate
ValkeyModuleString *ValkeyModule_GetClientCertificate(ValkeyModuleCtx *ctx,
uint64_t client_id);
可用版本 6.0.9
返回客户端用于验证此连接的 X.509 客户端证书。
返回值是一个已分配的 ValkeyModuleString
,它是 PEM (Base64) 格式编码的 X.509 证书。它应该由调用者释放(或自动释放)。
在以下情况下返回 NULL 值:
- 连接 ID 不存在
- 连接不是 TLS 连接
- 连接是 TLS 连接,但没有使用客户端证书
模块字典 API
实现了一个排序字典(实际上由基数树支持),具有通常的 get / set / del / num-items API,以及能够来回移动的迭代器。
ValkeyModule_CreateDict
ValkeyModuleDict *ValkeyModule_CreateDict(ValkeyModuleCtx *ctx);
可用版本 5.0.0
创建一个新字典。'ctx' 指针可以是当前模块上下文,也可以是 NULL,具体取决于您的需求。请遵循以下规则:
- 如果您计划保留对此字典的引用,并且该引用将在您创建它的模块回调时间之后仍然存在,请使用 NULL 上下文。
- 如果您在创建字典时没有可用上下文(当然...),请使用 NULL 上下文。
- 但是,如果字典的生命周期仅限于回调范围,请使用当前回调上下文作为“ctx”参数。在这种情况下,如果启用,您可以享受自动内存管理,它将回收字典内存,以及 Next / Prev 字典迭代器调用返回的字符串。
ValkeyModule_FreeDict
void ValkeyModule_FreeDict(ValkeyModuleCtx *ctx, ValkeyModuleDict *d);
可用版本 5.0.0
释放使用 ValkeyModule_CreateDict()
创建的字典。您只有在使用上下文而不是传递 NULL 创建字典时才需要传递上下文指针“ctx”。
ValkeyModule_DictSize
uint64_t ValkeyModule_DictSize(ValkeyModuleDict *d);
可用版本 5.0.0
返回字典的大小(键的数量)。
ValkeyModule_DictSetC
int ValkeyModule_DictSetC(ValkeyModuleDict *d,
void *key,
size_t keylen,
void *ptr);
可用版本 5.0.0
将指定的键存储到字典中,将其值设置为指针“ptr”。如果键添加成功,因为它尚不存在,则返回 VALKEYMODULE_OK
。否则,如果键已存在,则函数返回 VALKEYMODULE_ERR
。
ValkeyModule_DictReplaceC
int ValkeyModule_DictReplaceC(ValkeyModuleDict *d,
void *key,
size_t keylen,
void *ptr);
可用版本 5.0.0
类似于 ValkeyModule_DictSetC()
,但如果键已存在,则用新值替换键。
ValkeyModule_DictSet
int ValkeyModule_DictSet(ValkeyModuleDict *d,
ValkeyModuleString *key,
void *ptr);
可用版本 5.0.0
类似于 ValkeyModule_DictSetC()
,但将键作为 ValkeyModuleString
接受。
ValkeyModule_DictReplace
int ValkeyModule_DictReplace(ValkeyModuleDict *d,
ValkeyModuleString *key,
void *ptr);
可用版本 5.0.0
类似于 ValkeyModule_DictReplaceC()
,但将键作为 ValkeyModuleString
接受。
ValkeyModule_DictGetC
void *ValkeyModule_DictGetC(ValkeyModuleDict *d,
void *key,
size_t keylen,
int *nokey);
可用版本 5.0.0
返回存储在指定键的值。如果键不存在或您实际将 NULL 存储在键中,函数都返回 NULL。因此,可选地,如果 'nokey' 指针不为 NULL,它将通过引用设置为 1(如果键不存在)或 0(如果键存在)。
ValkeyModule_DictGet
void *ValkeyModule_DictGet(ValkeyModuleDict *d,
ValkeyModuleString *key,
int *nokey);
可用版本 5.0.0
类似于 ValkeyModule_DictGetC()
,但将键作为 ValkeyModuleString
接受。
ValkeyModule_DictDelC
int ValkeyModule_DictDelC(ValkeyModuleDict *d,
void *key,
size_t keylen,
void *oldval);
可用版本 5.0.0
从字典中删除指定的键,如果找到并删除了该键,则返回 VALKEYMODULE_OK
;否则,如果字典中没有该键,则返回 VALKEYMODULE_ERR
。操作成功时,如果 'oldval' 不为 NULL,则 '*oldval' 将设置为删除前存储在键处的值。使用此功能可以获取指向值(例如,为了释放它)的指针,而无需在删除键之前调用 ValkeyModule_DictGet()
。
ValkeyModule_DictDel
int ValkeyModule_DictDel(ValkeyModuleDict *d,
ValkeyModuleString *key,
void *oldval);
可用版本 5.0.0
类似于 ValkeyModule_DictDelC()
,但将键作为 ValkeyModuleString
获取。
ValkeyModule_DictIteratorStartC
ValkeyModuleDictIter *ValkeyModule_DictIteratorStartC(ValkeyModuleDict *d,
const char *op,
void *key,
size_t keylen);
可用版本 5.0.0
返回一个迭代器,该迭代器设置为通过应用操作符“op”从指定键开始迭代,“op”只是一个字符串,指定用于查找第一个元素的比较操作符。可用的操作符有:
^
– 查找第一个(字典序更小)键。$
– 查找最后一个(字典序更大)键。>
– 查找第一个大于指定键的元素。>=
– 查找第一个大于或等于指定键的元素。<
– 查找第一个小于指定键的元素。<=
– 查找第一个小于或等于指定键的元素。==
– 查找第一个与指定键完全匹配的元素。
请注意,对于 ^
和 $
,传入的键不使用,用户只需传入 NULL,长度为 0。
如果无法根据传入的键和操作符查找要开始迭代的元素,则 ValkeyModule_DictNext()
/ Prev() 在第一次调用时将直接返回 VALKEYMODULE_ERR
,否则它们将生成元素。
ValkeyModule_DictIteratorStart
ValkeyModuleDictIter *ValkeyModule_DictIteratorStart(ValkeyModuleDict *d,
const char *op,
ValkeyModuleString *key);
可用版本 5.0.0
与 ValkeyModule_DictIteratorStartC
完全相同,但键作为 ValkeyModuleString
传入。
ValkeyModule_DictIteratorStop
void ValkeyModule_DictIteratorStop(ValkeyModuleDictIter *di);
可用版本 5.0.0
释放使用 ValkeyModule_DictIteratorStart()
创建的迭代器。此调用是强制性的,否则会在模块中引入内存泄漏。
ValkeyModule_DictIteratorReseekC
int ValkeyModule_DictIteratorReseekC(ValkeyModuleDictIter *di,
const char *op,
void *key,
size_t keylen);
可用版本 5.0.0
在使用 ValkeyModule_DictIteratorStart()
创建迭代器后,可以通过此 API 调用更改迭代器当前选定的元素。根据操作符和键的结果与函数 ValkeyModule_DictIteratorStart()
完全相同,但在这种情况下,如果找到查找的元素,返回值仅为 VALKEYMODULE_OK
;如果无法查找指定元素,则返回 VALKEYMODULE_ERR
。您可以根据需要多次重新查找迭代器。
ValkeyModule_DictIteratorReseek
int ValkeyModule_DictIteratorReseek(ValkeyModuleDictIter *di,
const char *op,
ValkeyModuleString *key);
可用版本 5.0.0
类似于 ValkeyModule_DictIteratorReseekC()
,但将键作为 ValkeyModuleString
接受。
ValkeyModule_DictNextC
void *ValkeyModule_DictNextC(ValkeyModuleDictIter *di,
size_t *keylen,
void **dataptr);
可用版本 5.0.0
返回字典迭代器 di
的当前项并步进到下一个元素。如果迭代器已生成最后一个元素且没有其他元素可返回,则返回 NULL,否则提供一个指向表示键的字符串的指针,并且通过引用设置 *keylen
长度(如果 keylen 不为 NULL)。*dataptr
(如果不为 NULL)设置为存储在返回键处的指针的值作为辅助数据(如 ValkeyModule_DictSet
API 设置)。
用法示例:
... create the iterator here ...
char *key;
void *data;
while((key = ValkeyModule_DictNextC(iter,&keylen,&data)) != NULL) {
printf("%.*s %p\n", (int)keylen, key, data);
}
返回的指针类型为 void,因为有时将其转换为 char*
,有时转换为 unsigned char*
,具体取决于它是否包含二进制数据,因此此 API 使用起来更方便。
返回指针的有效性直到下次调用下一个/上一个迭代器步骤。一旦迭代器释放,指针也就不再有效。
ValkeyModule_DictPrevC
void *ValkeyModule_DictPrevC(ValkeyModuleDictIter *di,
size_t *keylen,
void **dataptr);
可用版本 5.0.0
此函数与 ValkeyModule_DictNext()
完全相同,但在返回迭代器中当前选定的元素后,它选择上一个元素(字典序更小)而不是下一个元素。
ValkeyModule_DictNext
ValkeyModuleString *ValkeyModule_DictNext(ValkeyModuleCtx *ctx,
ValkeyModuleDictIter *di,
void **dataptr);
可用版本 5.0.0
类似于 ValkeyModuleNextC()
,但不是返回内部分配的缓冲区和键长度,而是直接返回在指定上下文“ctx”中分配的模块字符串对象(可能为 NULL,与主 API ValkeyModule_CreateString
完全相同)。
返回的字符串对象在使用后应手动释放,或通过使用具有自动内存管理功能的上下文来释放。
ValkeyModule_DictPrev
ValkeyModuleString *ValkeyModule_DictPrev(ValkeyModuleCtx *ctx,
ValkeyModuleDictIter *di,
void **dataptr);
可用版本 5.0.0
类似于 ValkeyModule_DictNext()
,但在返回迭代器中当前选定的元素后,它选择上一个元素(字典序更小)而不是下一个元素。
ValkeyModule_DictCompareC
int ValkeyModule_DictCompareC(ValkeyModuleDictIter *di,
const char *op,
void *key,
size_t keylen);
可用版本 5.0.0
根据操作符“op”(有效操作符集合与 ValkeyModule_DictIteratorStart
相同),将迭代器当前指向的元素与由键/键长度指定的元素进行比较。如果比较成功,命令返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
。
这在需要只发出字典序范围时很有用,因此在循环中,当我们迭代元素时,也可以检查我们是否仍在范围内。
如果迭代器也达到了元素结束条件,函数返回 VALKEYMODULE_ERR
。
ValkeyModule_DictCompare
int ValkeyModule_DictCompare(ValkeyModuleDictIter *di,
const char *op,
ValkeyModuleString *key);
可用版本 5.0.0
类似于 ValkeyModule_DictCompareC
,但将与当前迭代器键进行比较的键作为 ValkeyModuleString
接受。
模块信息字段
ValkeyModule_InfoAddSection
int ValkeyModule_InfoAddSection(ValkeyModuleInfoCtx *ctx, const char *name);
可用版本 6.0.0
用于在添加任何字段之前启动一个新部分。部分名称将以 <modulename>_
为前缀,并且只能包含 A-Z、a-z、0-9。NULL 或空字符串表示使用默认部分(仅 <modulename>
)。当返回值为 VALKEYMODULE_ERR
时,该部分应该并且将被跳过。
ValkeyModule_InfoBeginDictField
int ValkeyModule_InfoBeginDictField(ValkeyModuleInfoCtx *ctx,
const char *name);
可用版本 6.0.0
开始一个字典字段,类似于 INFO KEYSPACE 中的字段。使用正常的 ValkeyModule_InfoAddField
* 函数向此字段添加项,并以 ValkeyModule_InfoEndDictField
结束。
ValkeyModule_InfoEndDictField
int ValkeyModule_InfoEndDictField(ValkeyModuleInfoCtx *ctx);
可用版本 6.0.0
结束一个字典字段,参见 ValkeyModule_InfoBeginDictField
。
ValkeyModule_InfoAddFieldString
int ValkeyModule_InfoAddFieldString(ValkeyModuleInfoCtx *ctx,
const char *field,
ValkeyModuleString *value);
可用版本 6.0.0
由 ValkeyModuleInfoFunc
用于添加信息字段。每个字段将自动以 <modulename>_
为前缀。字段名称或值不得包含 \r\n
或 :
。
ValkeyModule_InfoAddFieldCString
int ValkeyModule_InfoAddFieldCString(ValkeyModuleInfoCtx *ctx,
const char *field,
const char *value);
可用版本 6.0.0
参见 ValkeyModule_InfoAddFieldString()
。
ValkeyModule_InfoAddFieldDouble
int ValkeyModule_InfoAddFieldDouble(ValkeyModuleInfoCtx *ctx,
const char *field,
double value);
可用版本 6.0.0
参见 ValkeyModule_InfoAddFieldString()
。
ValkeyModule_InfoAddFieldLongLong
int ValkeyModule_InfoAddFieldLongLong(ValkeyModuleInfoCtx *ctx,
const char *field,
long long value);
可用版本 6.0.0
参见 ValkeyModule_InfoAddFieldString()
。
ValkeyModule_InfoAddFieldULongLong
int ValkeyModule_InfoAddFieldULongLong(ValkeyModuleInfoCtx *ctx,
const char *field,
unsigned long long value);
可用版本 6.0.0
参见 ValkeyModule_InfoAddFieldString()
。
ValkeyModule_RegisterInfoFunc
int ValkeyModule_RegisterInfoFunc(ValkeyModuleCtx *ctx,
ValkeyModuleInfoFunc cb);
可用版本 6.0.0
注册 INFO 命令的回调。回调应通过调用 ValkeyModule_InfoAddField*()
函数来添加 INFO 字段。
ValkeyModule_GetServerInfo
ValkeyModuleServerInfoData *ValkeyModule_GetServerInfo(ValkeyModuleCtx *ctx,
const char *section);
可用版本 6.0.0
获取服务器信息,类似于 INFO 命令返回的信息。此函数接受一个可选的“section”参数,该参数可以为 NULL。返回值包含输出,可与 ValkeyModule_ServerInfoGetField
等函数一起使用以获取单个字段。完成后,需要使用 ValkeyModule_FreeServerInfo
或启用的自动内存管理机制将其释放。
ValkeyModule_FreeServerInfo
void ValkeyModule_FreeServerInfo(ValkeyModuleCtx *ctx,
ValkeyModuleServerInfoData *data);
可用版本 6.0.0
释放使用 ValkeyModule_GetServerInfo()
创建的数据。只有在使用上下文而不是传递 NULL 创建字典时才需要传递上下文指针“ctx”。
ValkeyModule_ServerInfoGetField
ValkeyModuleString *ValkeyModule_ServerInfoGetField(ValkeyModuleCtx *ctx,
ValkeyModuleServerInfoData *data,
const char *field);
可用版本 6.0.0
从使用 ValkeyModule_GetServerInfo()
收集的数据中获取字段的值。只有在希望使用自动内存机制释放返回的字符串时才需要传递上下文指针“ctx”。如果未找到该字段,返回值将为 NULL。
ValkeyModule_ServerInfoGetFieldC
const char *ValkeyModule_ServerInfoGetFieldC(ValkeyModuleServerInfoData *data,
const char *field);
可用版本 6.0.0
类似于 ValkeyModule_ServerInfoGetField
,但返回一个 char*,调用者不应释放它。
ValkeyModule_ServerInfoGetFieldSigned
long long ValkeyModule_ServerInfoGetFieldSigned(ValkeyModuleServerInfoData *data,
const char *field,
int *out_err);
可用版本 6.0.0
从使用 ValkeyModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是数字或超出范围,则返回值将为 0,并且可选的 out_err
参数将设置为 VALKEYMODULE_ERR
。
ValkeyModule_ServerInfoGetFieldUnsigned
unsigned long long ValkeyModule_ServerInfoGetFieldUnsigned(ValkeyModuleServerInfoData *data,
const char *field,
int *out_err);
可用版本 6.0.0
从使用 ValkeyModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是数字或超出范围,则返回值将为 0,并且可选的 out_err
参数将设置为 VALKEYMODULE_ERR
。
ValkeyModule_ServerInfoGetFieldDouble
double ValkeyModule_ServerInfoGetFieldDouble(ValkeyModuleServerInfoData *data,
const char *field,
int *out_err);
可用版本 6.0.0
从使用 ValkeyModule_GetServerInfo()
收集的数据中获取字段的值。如果未找到该字段,或者它不是双精度浮点数,则返回值将为 0,并且可选的 out_err
参数将设置为 VALKEYMODULE_ERR
。
模块实用工具 API
ValkeyModule_GetRandomBytes
void ValkeyModule_GetRandomBytes(unsigned char *dst, size_t len);
可用版本 5.0.0
使用 SHA1 在计数器模式下,通过 /dev/urandom 初始化种子返回随机字节。此函数速度快,因此可以用于生成大量字节而不会影响操作系统熵池。目前此函数不是线程安全的。
ValkeyModule_GetRandomHexChars
void ValkeyModule_GetRandomHexChars(char *dst, size_t len);
可用版本 5.0.0
类似于 ValkeyModule_GetRandomBytes()
,但不是将字符串设置为随机字节,而是将字符串设置为十六进制字符集 [0-9a-f] 中的随机字符。
模块 API 导出/导入
ValkeyModule_ExportSharedAPI
int ValkeyModule_ExportSharedAPI(ValkeyModuleCtx *ctx,
const char *apiname,
void *func);
可用版本 5.0.4
此函数由模块调用,用于以给定名称导出某些 API。其他模块将能够通过调用对称函数 ValkeyModule_GetSharedAPI()
并将返回值转换为正确的函数指针来使用此 API。
如果名称尚未被占用,函数将返回 VALKEYMODULE_OK
,否则将返回 VALKEYMODULE_ERR
并且不执行任何操作。
重要:apiname 参数应为具有静态生命周期的字符串字面量。API 依赖于它将来始终有效的事实。
ValkeyModule_GetSharedAPI
void *ValkeyModule_GetSharedAPI(ValkeyModuleCtx *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 = ValkeyModule_GetSharedAPI("...");
if (myFunctionPointer == NULL) return 0;
return 1;
}
模块命令过滤器 API
ValkeyModule_RegisterCommandFilter
ValkeyModuleCommandFilter *ValkeyModule_RegisterCommandFilter(ValkeyModuleCtx *ctx,
ValkeyModuleCommandFilterFunc callback,
int flags);
可用版本 5.0.5
注册一个新的命令过滤函数。
命令过滤使模块能够通过插入到所有命令的执行流中来扩展服务器。
已注册的过滤器在服务器执行*任何*命令之前被调用。这包括核心服务器命令和任何模块注册的命令。过滤器适用于所有执行路径,包括:
- 通过客户端调用。
- 通过任何模块的
ValkeyModule_Call()
调用。 - 通过 Lua
server.call()
调用。 - 从主节点复制命令。
过滤器在特殊的过滤器上下文中执行,该上下文与 ValkeyModuleCtx
不同且更受限制。由于过滤器影响任何命令,因此必须以非常高效的方式实现,以减少对服务器性能的影响。所有需要有效上下文的模块 API 调用(例如 ValkeyModule_Call()
、ValkeyModule_OpenKey()
等)在过滤器上下文中不受支持。
ValkeyModuleCommandFilterCtx
可用于检查或修改执行的命令及其参数。由于过滤器在服务器开始处理命令之前执行,因此任何更改都将影响命令的处理方式。例如,模块可以通过以下方式覆盖服务器命令:
- 注册一个
MODULE.SET
命令,它实现SET
命令的扩展版本。 - 注册一个命令过滤器,该过滤器检测特定键模式上的
SET
调用。一旦检测到,过滤器将把第一个参数从SET
替换为MODULE.SET
。 - 当过滤器执行完成时,服务器会考虑新的命令名称,从而执行模块自己的命令。
请注意,在上述用例中,如果 MODULE.SET
本身使用 ValkeyModule_Call()
,则过滤器也将应用于该调用。如果不需要,可以在注册过滤器时设置 VALKEYMODULE_CMDFILTER_NOSELF
标志。
VALKEYMODULE_CMDFILTER_NOSELF
标志可防止源自模块自身的 ValkeyModule_Call()
的执行流到达过滤器。此标志对所有执行流(包括嵌套流)都有效,只要执行从模块的命令上下文或与阻塞命令关联的线程安全上下文开始。
分离的线程安全上下文与模块*不*关联,不能受此标志保护。
如果注册了多个过滤器(由相同或不同的模块),它们将按注册顺序执行。
ValkeyModule_UnregisterCommandFilter
int ValkeyModule_UnregisterCommandFilter(ValkeyModuleCtx *ctx,
ValkeyModuleCommandFilter *filter);
可用版本 5.0.5
取消注册命令过滤器。
ValkeyModule_CommandFilterArgsCount
int ValkeyModule_CommandFilterArgsCount(ValkeyModuleCommandFilterCtx *fctx);
可用版本 5.0.5
返回过滤命令的参数数量。参数数量包括命令本身。
ValkeyModule_CommandFilterArgGet
ValkeyModuleString *ValkeyModule_CommandFilterArgGet(ValkeyModuleCommandFilterCtx *fctx,
int pos);
可用版本 5.0.5
返回指定的命令参数。第一个参数(位置 0)是命令本身,其余是用户提供的参数。
ValkeyModule_CommandFilterArgInsert
int ValkeyModule_CommandFilterArgInsert(ValkeyModuleCommandFilterCtx *fctx,
int pos,
ValkeyModuleString *arg);
可用版本 5.0.5
通过在指定位置插入新参数来修改过滤命令。指定的 ValkeyModuleString
参数可能在过滤器上下文销毁后被服务器使用,因此它不得自动分配内存、释放或在其他地方使用。
ValkeyModule_CommandFilterArgReplace
int ValkeyModule_CommandFilterArgReplace(ValkeyModuleCommandFilterCtx *fctx,
int pos,
ValkeyModuleString *arg);
可用版本 5.0.5
通过用新参数替换现有参数来修改过滤命令。指定的 ValkeyModuleString
参数可能在过滤器上下文销毁后被服务器使用,因此它不得自动分配内存、释放或在其他地方使用。
ValkeyModule_CommandFilterArgDelete
int ValkeyModule_CommandFilterArgDelete(ValkeyModuleCommandFilterCtx *fctx,
int pos);
可用版本 5.0.5
通过删除指定位置的参数来修改过滤命令。
ValkeyModule_CommandFilterGetClientId
unsigned long long ValkeyModule_CommandFilterGetClientId(ValkeyModuleCommandFilterCtx *fctx);
可用版本 7.2.0
获取发出我们正在过滤的命令的客户端的客户端 ID。
ValkeyModule_MallocSize
size_t ValkeyModule_MallocSize(void *ptr);
可用版本 6.0.0
对于通过 ValkeyModule_Alloc()
或 ValkeyModule_Realloc()
分配的给定指针,返回为其分配的内存量。请注意,这可能与我们通过分配调用分配的内存不同(更大),因为有时底层分配器会分配更多内存。
ValkeyModule_MallocUsableSize
size_t ValkeyModule_MallocUsableSize(void *ptr);
可用版本 7.0.1
类似于 ValkeyModule_MallocSize
,区别在于 ValkeyModule_MallocUsableSize
返回模块可用的内存大小。
ValkeyModule_MallocSizeString
size_t ValkeyModule_MallocSizeString(ValkeyModuleString *str);
可用版本 7.0.0
与 ValkeyModule_MallocSize
相同,但适用于 ValkeyModuleString
指针。
ValkeyModule_MallocSizeDict
size_t ValkeyModule_MallocSizeDict(ValkeyModuleDict *dict);
可用版本 7.0.0
与 ValkeyModule_MallocSize
相同,但适用于 ValkeyModuleDict
指针。请注意,返回的值仅是底层结构的开销,不包括键和值的分配大小。
ValkeyModule_GetUsedMemoryRatio
float ValkeyModule_GetUsedMemoryRatio(void);
可用版本 6.0.0
返回一个介于 0 到 1 之间的数字,表示当前使用的内存量相对于服务器“maxmemory”配置的比例。
- 0 - 未配置内存限制。
- 0 到 1 之间 - 内存使用的百分比在 0-1 范围内标准化。
- 正好为 1 - 内存限制已达到。
- 大于 1 - 使用的内存超过配置限制。
扫描键空间和哈希
ValkeyModule_ScanCursorCreate
ValkeyModuleScanCursor *ValkeyModule_ScanCursorCreate(void);
可用版本 6.0.0
创建一个新游标以与 ValkeyModule_Scan
一起使用。
ValkeyModule_ScanCursorRestart
void ValkeyModule_ScanCursorRestart(ValkeyModuleScanCursor *cursor);
可用版本 6.0.0
重新启动现有游标。键将被重新扫描。
ValkeyModule_ScanCursorDestroy
void ValkeyModule_ScanCursorDestroy(ValkeyModuleScanCursor *cursor);
可用版本 6.0.0
销毁游标结构。
ValkeyModule_Scan
int ValkeyModule_Scan(ValkeyModuleCtx *ctx,
ValkeyModuleScanCursor *cursor,
ValkeyModuleScanCB fn,
void *privdata);
可用版本 6.0.0
扫描 API,允许模块扫描所选数据库中的所有键和值。
用于扫描实现的回调。
void scan_callback(ValkeyModuleCtx *ctx, ValkeyModuleString *keyname,
ValkeyModuleKey *key, void *privdata);
ctx
:为扫描提供的模块上下文。keyname
:由调用者拥有,如果在此函数之后使用,则需要保留。key
:包含键和值的信息,作为最佳努力提供,在某些情况下可能为 NULL,在这种情况下用户应(可以)使用ValkeyModule_OpenKey()
(和 CloseKey)。当提供时,它由调用者拥有,并在回调返回时释放。privdata
:提供给ValkeyModule_Scan()
的用户数据。
其使用方式:
ValkeyModuleScanCursor *c = ValkeyModule_ScanCursorCreate();
while(ValkeyModule_Scan(ctx, c, callback, privateData));
ValkeyModule_ScanCursorDestroy(c);
也可以在实际调用 ValkeyModule_Scan
期间获取锁时,从另一个线程使用此 API。
ValkeyModuleScanCursor *c = ValkeyModule_ScanCursorCreate();
ValkeyModule_ThreadSafeContextLock(ctx);
while(ValkeyModule_Scan(ctx, c, callback, privateData)){
ValkeyModule_ThreadSafeContextUnlock(ctx);
// do some background job
ValkeyModule_ThreadSafeContextLock(ctx);
}
ValkeyModule_ScanCursorDestroy(c);
如果还有更多元素要扫描,函数将返回 1,否则返回 0,如果调用失败,可能会设置 errno。
也可以使用 ValkeyModule_ScanCursorRestart
重新启动现有游标。
重要提示:此 API 在其提供的保证方面与 SCAN 命令非常相似。这意味着 API 可能会报告重复的键,但保证至少报告一次从扫描过程开始到结束存在的所有键。
注意:如果您在回调中进行数据库更改,您应该注意数据库的内部状态可能会更改。例如,删除或修改当前键是安全的,但删除任何其他键可能不安全。此外,在迭代时操作键空间可能会导致返回更多重复项。一个安全的模式是将要修改的键名存储在其他地方,并在迭代完成后再对键执行操作。然而,这可能会消耗大量内存,因此在迭代期间,如果可能且安全,直接对当前键进行操作可能更有意义。
ValkeyModule_ScanKey
int ValkeyModule_ScanKey(ValkeyModuleKey *key,
ValkeyModuleScanCursor *cursor,
ValkeyModuleScanKeyCB fn,
void *privdata);
可用版本 6.0.0
扫描 API,允许模块扫描哈希、集合或有序集合键中的元素。
用于扫描实现的回调。
void scan_callback(ValkeyModuleKey *key, ValkeyModuleString* field, ValkeyModuleString* value, void *privdata);
- key - 为扫描提供的键上下文。
- field - 字段名称,由调用者拥有,如果在此函数之后使用,则需要保留。
- value - 值字符串或集合类型的 NULL,由调用者拥有,如果在此函数之后使用,则需要保留。
- privdata - 提供给
ValkeyModule_ScanKey
的用户数据。
其使用方式:
ValkeyModuleScanCursor *c = ValkeyModule_ScanCursorCreate();
ValkeyModuleKey *key = ValkeyModule_OpenKey(...)
while(ValkeyModule_ScanKey(key, c, callback, privateData));
ValkeyModule_CloseKey(key);
ValkeyModule_ScanCursorDestroy(c);
也可以在实际调用 ValkeyModule_ScanKey
期间获取锁时,从另一个线程使用此 API,并且每次重新打开键。
ValkeyModuleScanCursor *c = ValkeyModule_ScanCursorCreate();
ValkeyModule_ThreadSafeContextLock(ctx);
ValkeyModuleKey *key = ValkeyModule_OpenKey(...)
while(ValkeyModule_ScanKey(ctx, c, callback, privateData)){
ValkeyModule_CloseKey(key);
ValkeyModule_ThreadSafeContextUnlock(ctx);
// do some background job
ValkeyModule_ThreadSafeContextLock(ctx);
ValkeyModuleKey *key = ValkeyModule_OpenKey(...)
}
ValkeyModule_CloseKey(key);
ValkeyModule_ScanCursorDestroy(c);
如果还有更多元素要扫描,函数将返回 1,否则返回 0,如果调用失败,可能会设置 errno。也可以使用 ValkeyModule_ScanCursorRestart
重新启动现有游标。
注意:在迭代对象时,某些操作是不安全的。例如,虽然 API 保证至少一次返回数据结构中从迭代开始到结束一致存在的所有元素(参见 HSCAN 和类似命令的文档),但您对元素的更改越多,您可能得到的重复项就越多。通常,删除数据结构的当前元素是安全的,而删除正在迭代的键则不安全。
模块 fork API
ValkeyModule_Fork
int ValkeyModule_Fork(ValkeyModuleForkDoneHandler cb, void *user_data);
可用版本 6.0.0
创建一个后台子进程,其中包含主进程当前冻结的快照,您可以在后台进行一些处理,而不会影响/冻结流量,也无需线程和 GIL 锁定。请注意,服务器只允许一个并发的 fork。当子进程想要退出时,它应该调用 ValkeyModule_ExitFromChild
。如果父进程想要杀死子进程,它应该调用 ValkeyModule_KillForkChild
。当子进程退出时(但不是被杀死时),done handler 回调将在父进程上执行。返回:失败时为 -1,成功时父进程将获得子进程的正 PID,子进程将获得 0。
ValkeyModule_SendChildHeartbeat
void ValkeyModule_SendChildHeartbeat(double progress);
可用版本 6.2.0
模块建议偶尔从 fork 子进程调用此函数,以便它可以向父进程报告进度和 COW 内存,这些将在 INFO 中报告。progress
参数应介于 0 和 1 之间,或在不可用时为 -1。
ValkeyModule_ExitFromChild
int ValkeyModule_ExitFromChild(int retcode);
可用版本 6.0.0
当您想终止子进程时,从子进程调用。retcode 将提供给在父进程上执行的完成处理程序。
ValkeyModule_KillForkChild
int ValkeyModule_KillForkChild(int child_pid);
可用版本 6.0.0
可用于从父进程杀死 fork 的子进程。child_pid
将是 ValkeyModule_Fork
的返回值。
服务器钩子实现
ValkeyModule_SubscribeToServerEvent
int ValkeyModule_SubscribeToServerEvent(ValkeyModuleCtx *ctx,
ValkeyModuleEvent event,
ValkeyModuleEventCallback callback);
可用版本 6.0.0
注册以便在发生指定服务器事件时通过回调获得通知。回调将事件作为参数调用,以及一个额外的 void 指针参数,该参数应转换为事件特定的特定类型(但许多事件将只使用 NULL,因为它们没有额外信息要传递给回调)。
如果回调为 NULL 且之前存在订阅,则模块将被取消订阅。如果之前存在订阅且回调不为 NULL,则旧回调将被新回调替换。
回调必须是以下类型:
int (*ValkeyModuleEventCallback)(ValkeyModuleCtx *ctx,
ValkeyModuleEvent eid,
uint64_t subevent,
void *data);
'ctx' 是一个普通的模块上下文,回调可以使用它来调用其他模块 API。'eid' 是事件本身,这仅在模块订阅了多个事件的情况下有用:使用此结构的 'id' 字段可以检查事件是否是我们使用此回调注册的事件之一。'subevent' 字段取决于触发的事件。
最后,'data' 指针可能会被填充,仅用于某些事件,并包含更多相关数据。
以下是您可以作为“eid”使用的事件列表以及相关的子事件:
-
ValkeyModuleEvent_ReplicationRoleChanged
:当实例从主节点切换到副本或反向切换时,此事件将被调用,但当副本仍为副本但开始与不同的主节点进行复制时,此事件也会被调用。
以下子事件可用:
VALKEYMODULE_SUBEVENT_REPLROLECHANGED_NOW_PRIMARY
VALKEYMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA
'data' 字段可以由回调转换为具有以下字段的
ValkeyModuleReplicationInfo
结构:int primary; // true if primary, false if replica char *primary_host; // primary instance hostname for NOW_REPLICA int primary_port; // primary 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
-
ValkeyModuleEvent_Persistence
RDB 保存或 AOF 重写开始和结束时会调用此事件。以下子事件可用:
VALKEYMODULE_SUBEVENT_PERSISTENCE_RDB_START
VALKEYMODULE_SUBEVENT_PERSISTENCE_AOF_START
VALKEYMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
VALKEYMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START
VALKEYMODULE_SUBEVENT_PERSISTENCE_ENDED
VALKEYMODULE_SUBEVENT_PERSISTENCE_FAILED
上述事件不仅在用户调用相关命令(如 BGSAVE)时触发,而且在由于内部服务器触发而发生保存操作或 AOF 重写时也会触发。SYNC_RDB_START 子事件由于 SAVE 命令、FLUSHALL 或服务器关闭而在前台发生,而其他 RDB 和 AOF 子事件在后台 fork 子进程中执行,因此模块采取的任何操作只能影响生成的 AOF 或 RDB,但不会反映在父进程中并影响连接的客户端和命令。另请注意,在 AOF 带有 rdb-preamble 的情况下,AOF_START 子事件最终可能会保存 RDB 内容。
-
ValkeyModuleEvent_FlushDB
发生了 FLUSHALL、FLUSHDB 或内部刷新(例如,由于复制,在副本同步之后)。以下子事件可用:
VALKEYMODULE_SUBEVENT_FLUSHDB_START
VALKEYMODULE_SUBEVENT_FLUSHDB_END
数据指针可以转换为一个带有以下字段的 ValkeyModuleFlushInfo 结构:
int32_t async; // True if the flush is done in a thread. // See for instance FLUSHALL ASYNC. // In this case the END callback is invoked // immediately after the database is put // in the free list of the thread. int32_t dbnum; // Flushed database number, -1 for all the DBs // in the case of the FLUSHALL operation.
启动事件在操作开始*之前*被调用,从而允许回调在尚未释放的键空间上调用 DBSIZE 或其他操作。
-
ValkeyModuleEvent_Loading
在加载操作时调用:在服务器启动时,以及在副本从主服务器加载 RDB 文件后的第一次同步之后。以下子事件可用:
VALKEYMODULE_SUBEVENT_LOADING_RDB_START
VALKEYMODULE_SUBEVENT_LOADING_AOF_START
VALKEYMODULE_SUBEVENT_LOADING_REPL_START
VALKEYMODULE_SUBEVENT_LOADING_ENDED
VALKEYMODULE_SUBEVENT_LOADING_FAILED
请注意,AOF 加载可能会在有 rdb-preamble 的情况下以 RDB 数据开始,在这种情况下,您将只收到一个 AOF_START 事件。
-
ValkeyModuleEvent_ClientChange
当客户端连接或断开连接时调用。数据指针可以转换为 ValkeyModuleClientInfo 结构,该结构在 ValkeyModule_GetClientInfoById() 中有文档说明。以下子事件可用:
VALKEYMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
VALKEYMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED
-
ValkeyModuleEvent_Shutdown
服务器正在关闭。没有子事件可用。
-
ValkeyModuleEvent_ReplicaChange
当实例(可以是主节点或副本)获得一个新的在线副本,或由于断开连接而失去一个副本时,此事件将被调用。以下子事件可用:
VALKEYMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE
VALKEYMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE
目前没有其他信息可用:服务器的未来版本将提供一个 API,用于枚举连接的副本及其状态。
-
ValkeyModuleEvent_CronLoop
当服务器调用 serverCron() 函数以进行某些簿记时,每次都会调用此事件。需要不时执行操作的模块可以使用此回调。通常,服务器每秒调用此函数 10 次,但这取决于“hz”配置。没有子事件可用。
数据指针可以转换为一个带有以下字段的 ValkeyModuleCronLoop 结构:
int32_t hz; // Approximate number of events per second.
-
ValkeyModuleEvent_PrimaryLinkChange
这用于副本,以在复制链接与我们的主节点功能正常(UP)或断开连接(DOWN)时发出通知。请注意,当仅连接到主节点时,链接不被视为 UP,只有当复制正常进行时才被视为 UP。以下子事件可用:
VALKEYMODULE_SUBEVENT_PRIMARY_LINK_UP
VALKEYMODULE_SUBEVENT_PRIMARY_LINK_DOWN
-
ValkeyModuleEvent_ModuleChange
当加载新模块或卸载模块时,此事件将被调用。以下子事件可用:
VALKEYMODULE_SUBEVENT_MODULE_LOADED
VALKEYMODULE_SUBEVENT_MODULE_UNLOADED
数据指针可以转换为一个带有以下字段的 ValkeyModuleModuleChange 结构:
const char* module_name; // Name of module loaded or unloaded. int32_t module_version; // Module version.
-
ValkeyModuleEvent_LoadingProgress
当 RDB 或 AOF 文件正在加载时,此事件会被重复调用。以下子事件可用:
VALKEYMODULE_SUBEVENT_LOADING_PROGRESS_RDB
VALKEYMODULE_SUBEVENT_LOADING_PROGRESS_AOF
数据指针可以转换为一个带有以下字段的 ValkeyModuleLoadingProgress 结构:
int32_t hz; // Approximate number of events per second. int32_t progress; // Approximate progress between 0 and 1024, // or -1 if unknown.
-
ValkeyModuleEvent_SwapDB
当 SWAPDB 命令成功执行时,此事件将被调用。目前此事件调用没有子事件可用。
数据指针可以转换为一个带有以下字段的 ValkeyModuleSwapDbInfo 结构:
int32_t dbnum_first; // Swap Db first dbnum int32_t dbnum_second; // Swap Db second dbnum
-
ValkeyModuleEvent_ReplBackup
警告:复制备份事件自 Redis OSS 7.0 起已弃用,并且永远不会触发。有关 repl-diskless-load 设置为 swapdb 时如何触发异步复制加载事件,请参阅 ValkeyModuleEvent_ReplAsyncLoad。
当 repl-diskless-load 配置设置为 swapdb 时调用,服务器需要备份当前数据库以便将来可能恢复。具有全局数据并可能带有 aux_load 和 aux_save 回调的模块可能需要使用此通知来备份/恢复/丢弃其全局变量。以下子事件可用:
VALKEYMODULE_SUBEVENT_REPL_BACKUP_CREATE
VALKEYMODULE_SUBEVENT_REPL_BACKUP_RESTORE
VALKEYMODULE_SUBEVENT_REPL_BACKUP_DISCARD
-
ValkeyModuleEvent_ReplAsyncLoad
当 repl-diskless-load 配置设置为 swapdb 且与具有相同数据集历史记录(匹配复制 ID)的主服务器进行复制时调用。在这种情况下,服务器在从套接字加载新数据库到内存时提供当前数据集。模块必须声明它们支持此机制才能激活它,通过 VALKEYMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD 标志。以下子事件可用:
VALKEYMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED
VALKEYMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED
VALKEYMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED
-
ValkeyModuleEvent_ForkChild
当一个 fork 子进程(AOFRW、RDBSAVE、模块 fork...)诞生/死亡时调用。以下子事件可用:
VALKEYMODULE_SUBEVENT_FORK_CHILD_BORN
VALKEYMODULE_SUBEVENT_FORK_CHILD_DIED
-
ValkeyModuleEvent_EventLoop
在每次事件循环迭代时调用,就在事件循环进入休眠状态之前或之后。以下子事件可用:
VALKEYMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP
VALKEYMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP
-
ValkeyModule_Event_Config
当配置事件发生时调用。以下子事件可用:
VALKEYMODULE_SUBEVENT_CONFIG_CHANGE
数据指针可以转换为一个带有以下字段的 ValkeyModuleConfigChange 结构:
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
-
ValkeyModule_Event_Key
当键从键空间中删除时调用。我们无法在事件中修改任何键。以下子事件可用:
VALKEYMODULE_SUBEVENT_KEY_DELETED
VALKEYMODULE_SUBEVENT_KEY_EXPIRED
VALKEYMODULE_SUBEVENT_KEY_EVICTED
VALKEYMODULE_SUBEVENT_KEY_OVERWRITTEN
数据指针可以转换为一个带有以下字段的 ValkeyModuleKeyInfo 结构:
ValkeyModuleKey *key; // Key name
如果模块成功订阅了指定事件,函数返回 VALKEYMODULE_OK
。如果从错误上下文调用 API 或给定不支持的事件,则返回 VALKEYMODULE_ERR
。
ValkeyModule_IsSubEventSupported
int ValkeyModule_IsSubEventSupported(ValkeyModuleEvent event,
int64_t subevent);
可用版本 6.0.9
对于给定的服务器事件和子事件,如果子事件不受支持则返回零,否则返回非零值。
模块配置 API
ValkeyModule_RegisterStringConfig
int ValkeyModule_RegisterStringConfig(ValkeyModuleCtx *ctx,
const char *name,
const char *default_val,
unsigned int flags,
ValkeyModuleConfigGetStringFunc getfn,
ValkeyModuleConfigSetStringFunc setfn,
ValkeyModuleConfigApplyFunc applyfn,
void *privdata);
可用版本 7.0.0
创建字符串配置,用户可以通过服务器配置文件、CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与其交互。
实际的配置值由模块拥有,并且提供给服务器的 getfn
、setfn
和可选的 applyfn
回调用于访问或操作该值。getfn
回调从模块检索值,而 setfn
回调提供要存储到模块配置中的值。可选的 applyfn
回调在 CONFIG SET
命令使用 setfn
回调修改一个或多个配置后调用,可用于在多个配置一起更改后原子地应用配置。如果单个 CONFIG SET
命令设置了多个具有 applyfn
回调的配置,则如果它们的 applyfn
函数和 privdata
指针相同,它们将被去重,并且回调只运行一次。setfn
和 applyfn
都可以返回错误,如果提供的值无效或无法使用。配置还声明值的类型,该类型由服务器验证并提供给模块。配置系统提供以下类型:
- 字符串:二进制安全字符串数据。
- 枚举:有限数量的字符串令牌之一,在注册期间提供。
- 数字:64 位有符号整数,也支持最小值和最大值。
- 布尔:是或否值。
setfn
回调在值成功应用时应返回 VALKEYMODULE_OK
。如果值无法应用,它也可以返回 VALKEYMODULE_ERR
,并且可以将 *err 指针设置为一个 ValkeyModuleString
错误消息以提供给客户端。此 ValkeyModuleString
将在从 set 回调返回后由服务器释放。
所有配置都以名称、类型、默认值、在回调中可用的私有数据以及修改配置行为的多个标志进行注册。名称只能包含字母数字字符或破折号。支持的标志有:
VALKEYMODULE_CONFIG_DEFAULT
:配置的默认标志。这将创建一个可以在启动后修改的配置。VALKEYMODULE_CONFIG_IMMUTABLE
:此配置只能在加载时提供。VALKEYMODULE_CONFIG_SENSITIVE
:此配置中存储的值将从所有日志记录中编辑掉。VALKEYMODULE_CONFIG_HIDDEN
:名称在CONFIG GET
模式匹配中被隐藏。VALKEYMODULE_CONFIG_PROTECTED
:此配置只能根据 enable-protected-configs 的值进行修改。VALKEYMODULE_CONFIG_DENY_LOADING
:当服务器正在加载数据时,此配置不可修改。VALKEYMODULE_CONFIG_MEMORY
:对于数字配置,此配置会将数据单位表示法转换为其字节等效值。VALKEYMODULE_CONFIG_BITFLAGS
:对于枚举配置,此配置将允许将多个条目组合为位标志。
默认值在启动时用于设置值,如果未通过配置文件或命令行提供。默认值也用于在配置重写时进行比较。
注意事项
- 在字符串配置设置中,传递给 set 回调的字符串将在执行后释放,模块必须保留它。
- 在字符串配置获取中,字符串不会被消耗,并且在执行后仍然有效。
示例实现:
ValkeyModuleString *strval;
int adjustable = 1;
ValkeyModuleString *getStringConfigCommand(const char *name, void *privdata) {
return strval;
}
int setStringConfigCommand(const char *name, ValkeyModuleString *new, void *privdata, ValkeyModuleString **err) {
if (adjustable) {
ValkeyModule_Free(strval);
ValkeyModule_RetainString(NULL, new);
strval = new;
return VALKEYMODULE_OK;
}
*err = ValkeyModule_CreateString(NULL, "Not adjustable.", 15);
return VALKEYMODULE_ERR;
}
...
ValkeyModule_RegisterStringConfig(ctx, "string", NULL, VALKEYMODULE_CONFIG_DEFAULT, getStringConfigCommand,
setStringConfigCommand, NULL, NULL);
如果注册失败,则返回 VALKEYMODULE_ERR
并设置以下 errno 之一:
- EBUSY:在
ValkeyModule_OnLoad
之外注册配置。 - EINVAL:为注册提供的标志无效,或配置名称包含无效字符。
- EALREADY:提供的配置名称已被使用。
ValkeyModule_RegisterBoolConfig
int ValkeyModule_RegisterBoolConfig(ValkeyModuleCtx *ctx,
const char *name,
int default_val,
unsigned int flags,
ValkeyModuleConfigGetBoolFunc getfn,
ValkeyModuleConfigSetBoolFunc setfn,
ValkeyModuleConfigApplyFunc applyfn,
void *privdata);
可用版本 7.0.0
创建一个布尔配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与其交互。有关配置的详细信息,请参阅 ValkeyModule_RegisterStringConfig
。
ValkeyModule_RegisterEnumConfig
int ValkeyModule_RegisterEnumConfig(ValkeyModuleCtx *ctx,
const char *name,
int default_val,
unsigned int flags,
const char **enum_values,
const int *int_values,
int num_enum_vals,
ValkeyModuleConfigGetEnumFunc getfn,
ValkeyModuleConfigSetEnumFunc setfn,
ValkeyModuleConfigApplyFunc applyfn,
void *privdata);
可用版本 7.0.0
创建一个枚举配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与其交互。枚举配置是一组字符串令牌到相应整数值的映射,其中字符串值暴露给客户端,但整数值传递给服务器和模块。这些值在 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 VALKEYMODULE_OK;
}
...
ValkeyModule_RegisterEnumConfig(ctx, "enum", 0, VALKEYMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 3,
getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);
请注意,您可以使用 VALKEYMODULE_CONFIG_BITFLAGS
,以便将多个枚举字符串组合成一个整数作为位标志,在这种情况下,您可能希望对枚举进行排序,以便首选组合首先出现。
有关配置的详细通用信息,请参阅 ValkeyModule_RegisterStringConfig
。
ValkeyModule_RegisterNumericConfig
int ValkeyModule_RegisterNumericConfig(ValkeyModuleCtx *ctx,
const char *name,
long long default_val,
unsigned int flags,
long long min,
long long max,
ValkeyModuleConfigGetNumericFunc getfn,
ValkeyModuleConfigSetNumericFunc setfn,
ValkeyModuleConfigApplyFunc applyfn,
void *privdata);
可用版本 7.0.0
创建一个整数配置,服务器客户端可以通过 CONFIG SET
、CONFIG GET
和 CONFIG REWRITE
命令与其交互。有关配置的详细信息,请参阅 ValkeyModule_RegisterStringConfig
。
ValkeyModule_LoadConfigs
int ValkeyModule_LoadConfigs(ValkeyModuleCtx *ctx);
可用版本 7.0.0
在模块加载时应用所有待处理的配置。这应该在模块的所有配置都在 ValkeyModule_OnLoad
中注册后调用。如果在 ValkeyModule_OnLoad
之外调用,则返回 VALKEYMODULE_ERR
。当配置在 MODULE LOADEX
中提供或作为启动参数提供时,需要调用此 API。
RDB 加载/保存 API
ValkeyModule_RdbStreamCreateFromFile
ValkeyModuleRdbStream *ValkeyModule_RdbStreamCreateFromFile(const char *filename);
可用版本 7.2.0
创建流对象以从文件中保存/加载 RDB。
此函数返回一个指向 ValkeyModuleRdbStream
的指针,该指针由调用者拥有。它需要调用 ValkeyModule_RdbStreamFree()
来释放对象。
ValkeyModule_RdbStreamFree
void ValkeyModule_RdbStreamFree(ValkeyModuleRdbStream *stream);
可用版本 7.2.0
释放 RDB 流对象。
ValkeyModule_RdbLoad
int ValkeyModule_RdbLoad(ValkeyModuleCtx *ctx,
ValkeyModuleRdbStream *stream,
int flags);
可用版本 7.2.0
从 stream
加载 RDB 文件。数据集将首先被清除,然后 RDB 文件将被加载。
flags
必须为零。此参数供将来使用。
成功时返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno。
示例
ValkeyModuleRdbStream *s = ValkeyModule_RdbStreamCreateFromFile("exp.rdb");
ValkeyModule_RdbLoad(ctx, s, 0);
ValkeyModule_RdbStreamFree(s);
ValkeyModule_RdbSave
int ValkeyModule_RdbSave(ValkeyModuleCtx *ctx,
ValkeyModuleRdbStream *stream,
int flags);
可用版本 7.2.0
将数据集保存到 RDB 流。
flags
必须为零。此参数供将来使用。
成功时返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
并相应设置 errno。
示例
ValkeyModuleRdbStream *s = ValkeyModule_RdbStreamCreateFromFile("exp.rdb");
ValkeyModule_RdbSave(ctx, s, 0);
ValkeyModule_RdbStreamFree(s);
ValkeyModule_RegisterScriptingEngine
int ValkeyModule_RegisterScriptingEngine(ValkeyModuleCtx *module_ctx,;
可用版本 8.1.0
在服务器中注册一个新的脚本引擎。
-
module_ctx
:模块上下文对象。 -
engine_name
:脚本引擎的名称。此名称将与使用 shebang 在脚本头中指定的引擎名称匹配。 -
engine_ctx
:引擎特定上下文指针。 -
engine_methods
:包含脚本引擎回调函数指针的结构体。
如果引擎注册成功,则返回 VALKEYMODULE_OK
,如果发生某些故障,则返回 VALKEYMODULE_ERR
。如果发生故障,将记录错误消息。
ValkeyModule_UnregisterScriptingEngine
int ValkeyModule_UnregisterScriptingEngine(ValkeyModuleCtx *ctx,
const char *engine_name);
可用版本 8.1.0
从服务器中删除脚本引擎。
engine_name
是脚本引擎的名称。
返回 VALKEYMODULE_OK
。
ValkeyModule_GetFunctionExecutionState
ValkeyModuleScriptingEngineExecutionState ValkeyModule_GetFunctionExecutionState(;
可用版本 8.1.0
返回脚本引擎正在执行的当前函数的状态。
server_ctx
是服务器运行时上下文。
如果函数已经被 SCRIPT KILL
或 FUNCTION KILL
杀死,它将返回 VMSE_STATE_KILLED
。
Key 淘汰 API
ValkeyModule_SetLRU
int ValkeyModule_SetLRU(ValkeyModuleKey *key, mstime_t lru_idle);
可用版本 6.0.0
设置键的上次访问时间,用于基于 LRU 的逐出。如果服务器的 maxmemory 策略是基于 LFU 的,则不相关。值是空闲时间(毫秒)。如果 LRU 已更新,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetLRU
int ValkeyModule_GetLRU(ValkeyModuleKey *key, mstime_t *lru_idle);
可用版本 6.0.0
获取键的上次访问时间。值是空闲时间(毫秒),如果服务器的逐出策略是基于 LFU 的,则为 -1。当键有效时返回 VALKEYMODULE_OK
。
ValkeyModule_SetLFU
int ValkeyModule_SetLFU(ValkeyModuleKey *key, long long lfu_freq);
可用版本 6.0.0
设置键的访问频率。仅当服务器的 maxmemory 策略基于 LFU 时才相关。频率是一个对数计数器,仅提供访问频率的指示(必须 <= 255)。如果 LFU 已更新,则返回 VALKEYMODULE_OK
,否则返回 VALKEYMODULE_ERR
。
ValkeyModule_GetLFU
int ValkeyModule_GetLFU(ValkeyModuleKey *key, long long *lfu_freq);
可用版本 6.0.0
获取键的访问频率,如果服务器的逐出策略不是基于 LFU 的,则为 -1。当键有效时返回 VALKEYMODULE_OK
。
杂项 API
ValkeyModule_GetModuleOptionsAll
int ValkeyModule_GetModuleOptionsAll(void);
可用版本 7.2.0
返回完整的模块选项标志掩码,模块可以使用返回值检查当前使用的服务器版本是否支持某个模块选项集。示例:
int supportedFlags = ValkeyModule_GetModuleOptionsAll();
if (supportedFlags & VALKEYMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS) {
// VALKEYMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is supported
} else{
// VALKEYMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is not supported
}
ValkeyModule_GetContextFlagsAll
int ValkeyModule_GetContextFlagsAll(void);
可用版本 6.0.9
返回完整的 ContextFlags 掩码,模块可以使用返回值检查当前使用的服务器版本是否支持某个标志集。示例:
int supportedFlags = ValkeyModule_GetContextFlagsAll();
if (supportedFlags & VALKEYMODULE_CTX_FLAGS_MULTI) {
// VALKEYMODULE_CTX_FLAGS_MULTI is supported
} else{
// VALKEYMODULE_CTX_FLAGS_MULTI is not supported
}
ValkeyModule_GetKeyspaceNotificationFlagsAll
int ValkeyModule_GetKeyspaceNotificationFlagsAll(void);
可用版本 6.0.9
返回完整的 KeyspaceNotification 掩码,模块可以使用返回值检查当前使用的服务器版本是否支持某个标志集。示例:
int supportedFlags = ValkeyModule_GetKeyspaceNotificationFlagsAll();
if (supportedFlags & VALKEYMODULE_NOTIFY_LOADED) {
// VALKEYMODULE_NOTIFY_LOADED is supported
} else{
// VALKEYMODULE_NOTIFY_LOADED is not supported
}
ValkeyModule_GetServerVersion
int ValkeyModule_GetServerVersion(void);
可用版本 6.0.9
以 0x00MMmmpp 格式返回服务器版本。例如,对于 6.0.7,返回值为 0x00060007。
ValkeyModule_GetTypeMethodVersion
int ValkeyModule_GetTypeMethodVersion(void);
可用版本 6.2.0
返回 VALKEYMODULE_TYPE_METHOD_VERSION
的当前服务器运行时值。在调用 ValkeyModule_CreateDataType
时可以使用它来了解 ValkeyModuleTypeMethods
的哪些字段将受支持,哪些将被忽略。
ValkeyModule_ModuleTypeReplaceValue
int ValkeyModule_ModuleTypeReplaceValue(ValkeyModuleKey *key,
moduleType *mt,
void *new_value,
void **old_value);
可用版本 6.0.0
替换分配给模块类型的值。
键必须打开以进行写入,具有现有值,并且具有与调用者指定的模块类型匹配的 moduleType。
与将释放旧值的 ValkeyModule_ModuleTypeSetValue()
不同,此函数只是将旧值与新值交换。
成功时函数返回 VALKEYMODULE_OK
,错误时(例如):
- 键未打开以进行写入。
- 键不是模块数据类型键。
- 键是模块数据类型,但不是 'mt'。
如果 old_value
不为 NULL,则通过引用返回旧值。
ValkeyModule_GetCommandKeysWithFlags
int *ValkeyModule_GetCommandKeysWithFlags(ValkeyModuleCtx *ctx,
ValkeyModuleString **argv,
int argc,
int *num_keys,
int **out_flags);
可用版本 7.0.0
对于指定的命令,解析其参数并返回一个包含所有键名参数索引的数组。此函数本质上是执行 COMMAND GETKEYS
的一种更高效方式。
out_flags
参数是可选的,可以设置为 NULL。提供时,它会填充与返回数组中键索引匹配的 VALKEYMODULE_CMD_KEY_
标志。
NULL 返回值表示指定的命令没有键,或者出现了错误情况。错误情况通过设置 errno 表示,如下所示:
- ENOENT:指定命令不存在。
- EINVAL:指定了无效的命令参数个数。
注意:返回的数组不是一个模块对象,因此即使使用了自动内存管理也不会自动释放。调用者必须显式调用 ValkeyModule_Free()
来释放它,如果使用了 out_flags
指针,也需要同样处理。
ValkeyModule_GetCommandKeys
int *ValkeyModule_GetCommandKeys(ValkeyModuleCtx *ctx,
ValkeyModuleString **argv,
int argc,
int *num_keys);
可用版本 6.0.9
当不需要标志时,与 ValkeyModule_GetCommandKeysWithFlags
相同。
ValkeyModule_GetCurrentCommandName
const char *ValkeyModule_GetCurrentCommandName(ValkeyModuleCtx *ctx);
可用版本 6.2.5
返回当前正在运行的命令的名称
碎片整理 API
ValkeyModule_RegisterDefragFunc
int ValkeyModule_RegisterDefragFunc(ValkeyModuleCtx *ctx,
ValkeyModuleDefragFunc cb);
可用版本 6.2.0
注册一个用于全局数据的碎片整理回调,即模块可能分配的任何不绑定到特定数据类型的数据。
ValkeyModule_DefragShouldStop
int ValkeyModule_DefragShouldStop(ValkeyModuleDefragCtx *ctx);
可用版本 6.2.0
当数据类型碎片整理回调遍历复杂结构时,应定期调用此函数。返回零(false)表示回调可以继续其工作。非零值(true)表示它应该停止。
当停止时,回调可以使用 ValkeyModule_DefragCursorSet()
来存储其位置,以便以后可以使用 ValkeyModule_DefragCursorGet()
恢复碎片整理。
当停止且还有更多工作待完成时,回调应返回 1。否则,应返回 0。
注意:模块应考虑此函数的调用频率,因此通常在两次调用之间进行小批量工作是有意义的。
ValkeyModule_DefragCursorSet
int ValkeyModule_DefragCursorSet(ValkeyModuleDefragCtx *ctx,
unsigned long cursor);
可用版本 6.2.0
存储任意游标值以供将来重用。
仅当 ValkeyModule_DefragShouldStop()
返回非零值且碎片整理回调即将退出而未完全遍历其数据类型时,才应调用此函数。
此行为仅限于执行延迟碎片整理的情况。延迟碎片整理是为实现 free_effort
回调并返回的 free_effort
值大于碎片整理 'active-defrag-max-scan-fields' 配置指令的键选择的。
较小的键、未实现 free_effort
的键或全局碎片整理回调在延迟碎片整理模式下不会被调用。在这些情况下,调用此函数将返回 VALKEYMODULE_ERR
。
模块可以使用游标来表示模块数据类型中的某些进展。模块还可以在本地存储额外的游标相关信息,并使用游标作为指示新键遍历何时开始的标志。这是可能的,因为 API 保证不会对多个键进行并发碎片整理。
ValkeyModule_DefragCursorGet
int ValkeyModule_DefragCursorGet(ValkeyModuleDefragCtx *ctx,
unsigned long *cursor);
可用版本 6.2.0
获取先前使用 ValkeyModule_DefragCursorSet()
存储的游标值。
如果不是为延迟碎片整理操作调用,则将返回 VALKEYMODULE_ERR
,并且应忽略游标。有关碎片整理游标的更多详细信息,请参阅 ValkeyModule_DefragCursorSet()
。
ValkeyModule_DefragAlloc
void *ValkeyModule_DefragAlloc(ValkeyModuleDefragCtx *ctx, void *ptr);
可用版本 6.2.0
对先前由 ValkeyModule_Alloc
、ValkeyModule_Calloc
等分配的内存进行碎片整理。碎片整理过程涉及分配一个新的内存块并将内容复制到其中,类似于 realloc()
。
如果碎片整理不必要,则返回 NULL,并且该操作没有其他影响。
如果返回非 NULL 值,调用者应使用新指针而不是旧指针,并更新对旧指针的任何引用,旧指针不得再次使用。
ValkeyModule_DefragValkeyModuleString
ValkeyModuleString *ValkeyModule_DefragValkeyModuleString(ValkeyModuleDefragCtx *ctx,
ValkeyModuleString *str);
可用版本 7.2.5
对先前由 ValkeyModule_Alloc
、ValkeyModule_Calloc
等分配的 ValkeyModuleString
进行碎片整理。有关碎片整理过程如何工作的更多信息,请参阅 ValkeyModule_DefragAlloc()
。
注意:只能对具有单一引用的字符串进行碎片整理。通常这意味着使用 ValkeyModule_RetainString
或 ValkeyModule_HoldString
保留的字符串可能无法进行碎片整理。一个例外是命令参数 (argvs),如果被模块保留,它们最终将只有一个引用(因为服务器端的引用在命令回调返回后立即被丢弃)。
ValkeyModule_GetKeyNameFromDefragCtx
const ValkeyModuleString *ValkeyModule_GetKeyNameFromDefragCtx(ValkeyModuleDefragCtx *ctx);
可用版本 7.0.0
返回当前正在处理的键的名称。不保证键名始终可用,因此此函数可能返回 NULL。
ValkeyModule_GetDbIdFromDefragCtx
int ValkeyModule_GetDbIdFromDefragCtx(ValkeyModuleDefragCtx *ctx);
可用版本 7.0.0
返回当前正在处理的键的数据库 ID。不保证此信息始终可用,因此可能返回 -1。
函数索引
ValkeyModule_ACLAddLogEntry
ValkeyModule_ACLAddLogEntryByUserName
ValkeyModule_ACLCheckChannelPermissions
ValkeyModule_ACLCheckCommandPermissions
ValkeyModule_ACLCheckKeyPermissions
ValkeyModule_AbortBlock
ValkeyModule_AddACLCategory
ValkeyModule_AddPostNotificationJob
ValkeyModule_Alloc
ValkeyModule_AuthenticateClientWithACLUser
ValkeyModule_AuthenticateClientWithUser
ValkeyModule_AutoMemory
ValkeyModule_AvoidReplicaTraffic
ValkeyModule_BlockClient
ValkeyModule_BlockClientGetPrivateData
ValkeyModule_BlockClientOnAuth
ValkeyModule_BlockClientOnKeys
ValkeyModule_BlockClientOnKeysWithFlags
ValkeyModule_BlockClientSetPrivateData
ValkeyModule_BlockedClientDisconnected
ValkeyModule_BlockedClientMeasureTimeEnd
ValkeyModule_BlockedClientMeasureTimeStart
ValkeyModule_CachedMicroseconds
ValkeyModule_Call
ValkeyModule_CallReplyArrayElement
ValkeyModule_CallReplyAttribute
ValkeyModule_CallReplyAttributeElement
ValkeyModule_CallReplyBigNumber
ValkeyModule_CallReplyBool
ValkeyModule_CallReplyDouble
ValkeyModule_CallReplyInteger
ValkeyModule_CallReplyLength
ValkeyModule_CallReplyMapElement
ValkeyModule_CallReplyPromiseAbort
ValkeyModule_CallReplyPromiseSetUnblockHandler
ValkeyModule_CallReplyProto
ValkeyModule_CallReplySetElement
ValkeyModule_CallReplyStringPtr
ValkeyModule_CallReplyType
ValkeyModule_CallReplyVerbatim
ValkeyModule_Calloc
ValkeyModule_ChannelAtPosWithFlags
ValkeyModule_CloseKey
ValkeyModule_ClusterCanonicalKeyNameInSlot
ValkeyModule_ClusterKeySlot
ValkeyModule_CommandFilterArgDelete
ValkeyModule_CommandFilterArgGet
ValkeyModule_CommandFilterArgInsert
ValkeyModule_CommandFilterArgReplace
ValkeyModule_CommandFilterArgsCount
ValkeyModule_CommandFilterGetClientId
ValkeyModule_CreateCommand
ValkeyModule_CreateDataType
ValkeyModule_CreateDict
ValkeyModule_CreateModuleUser
ValkeyModule_CreateString
ValkeyModule_CreateStringFromCallReply
ValkeyModule_CreateStringFromDouble
ValkeyModule_CreateStringFromLongDouble
ValkeyModule_CreateStringFromLongLong
ValkeyModule_CreateStringFromStreamID
ValkeyModule_CreateStringFromString
ValkeyModule_CreateStringFromULongLong
ValkeyModule_CreateStringPrintf
ValkeyModule_CreateSubcommand
ValkeyModule_CreateTimer
ValkeyModule_DbSize
ValkeyModule_DeauthenticateAndCloseClient
ValkeyModule_DefragAlloc
ValkeyModule_DefragCursorGet
ValkeyModule_DefragCursorSet
ValkeyModule_DefragShouldStop
ValkeyModule_DefragValkeyModuleString
ValkeyModule_DeleteKey
ValkeyModule_DictCompare
ValkeyModule_DictCompareC
ValkeyModule_DictDel
ValkeyModule_DictDelC
ValkeyModule_DictGet
ValkeyModule_DictGetC
ValkeyModule_DictIteratorReseek
ValkeyModule_DictIteratorReseekC
ValkeyModule_DictIteratorStart
ValkeyModule_DictIteratorStartC
ValkeyModule_DictIteratorStop
ValkeyModule_DictNext
ValkeyModule_DictNextC
ValkeyModule_DictPrev
ValkeyModule_DictPrevC
ValkeyModule_DictReplace
ValkeyModule_DictReplaceC
ValkeyModule_DictSet
ValkeyModule_DictSetC
ValkeyModule_DictSize
ValkeyModule_DigestAddLongLong
ValkeyModule_DigestAddStringBuffer
ValkeyModule_DigestEndSequence
ValkeyModule_EmitAOF
ValkeyModule_EventLoopAdd
ValkeyModule_EventLoopAddOneShot
ValkeyModule_EventLoopDel
ValkeyModule_ExitFromChild
ValkeyModule_ExportSharedAPI
ValkeyModule_Fork
ValkeyModule_Free
ValkeyModule_FreeCallReply
ValkeyModule_FreeClusterNodesList
ValkeyModule_FreeDict
ValkeyModule_FreeModuleUser
ValkeyModule_FreeServerInfo
ValkeyModule_FreeString
ValkeyModule_FreeThreadSafeContext
ValkeyModule_GetAbsExpire
ValkeyModule_GetBlockedClientHandle
ValkeyModule_GetBlockedClientPrivateData
ValkeyModule_GetBlockedClientReadyKey
ValkeyModule_GetClientCertificate
ValkeyModule_GetClientId
ValkeyModule_GetClientInfoById
ValkeyModule_GetClientNameById
ValkeyModule_GetClientUserNameById
ValkeyModule_GetClusterNodeInfo
ValkeyModule_GetClusterNodeInfoForClient
ValkeyModule_GetClusterNodesList
ValkeyModule_GetClusterSize
ValkeyModule_GetCommand
ValkeyModule_GetCommandKeys
ValkeyModule_GetCommandKeysWithFlags
ValkeyModule_GetContextFlags
ValkeyModule_GetContextFlagsAll
ValkeyModule_GetCurrentCommandName
ValkeyModule_GetCurrentUserName
ValkeyModule_GetDbIdFromDefragCtx
ValkeyModule_GetDbIdFromDigest
ValkeyModule_GetDbIdFromIO
ValkeyModule_GetDbIdFromModuleKey
ValkeyModule_GetDbIdFromOptCtx
ValkeyModule_GetDetachedThreadSafeContext
ValkeyModule_GetExpire
ValkeyModule_GetFunctionExecutionState
ValkeyModule_GetKeyNameFromDefragCtx
ValkeyModule_GetKeyNameFromDigest
ValkeyModule_GetKeyNameFromIO
ValkeyModule_GetKeyNameFromModuleKey
ValkeyModule_GetKeyNameFromOptCtx
ValkeyModule_GetKeyspaceNotificationFlagsAll
ValkeyModule_GetLFU
ValkeyModule_GetLRU
ValkeyModule_GetModuleOptionsAll
ValkeyModule_GetModuleUserACLString
ValkeyModule_GetModuleUserFromUserName
ValkeyModule_GetMyClusterID
ValkeyModule_GetNotifyKeyspaceEvents
ValkeyModule_GetOpenKeyModesAll
ValkeyModule_GetRandomBytes
ValkeyModule_GetRandomHexChars
ValkeyModule_GetSelectedDb
ValkeyModule_GetServerInfo
ValkeyModule_GetServerVersion
ValkeyModule_GetSharedAPI
ValkeyModule_GetThreadSafeContext
ValkeyModule_GetTimerInfo
ValkeyModule_GetToDbIdFromOptCtx
ValkeyModule_GetToKeyNameFromOptCtx
ValkeyModule_GetTypeMethodVersion
ValkeyModule_GetUsedMemoryRatio
ValkeyModule_HashGet
ValkeyModule_HashSet
ValkeyModule_HoldString
ValkeyModule_InfoAddFieldCString
ValkeyModule_InfoAddFieldDouble
ValkeyModule_InfoAddFieldLongLong
ValkeyModule_InfoAddFieldString
ValkeyModule_InfoAddFieldULongLong
ValkeyModule_InfoAddSection
ValkeyModule_InfoBeginDictField
ValkeyModule_InfoEndDictField
ValkeyModule_IsBlockedReplyRequest
ValkeyModule_IsBlockedTimeoutRequest
ValkeyModule_IsChannelsPositionRequest
ValkeyModule_IsIOError
ValkeyModule_IsKeysPositionRequest
ValkeyModule_IsModuleNameBusy
ValkeyModule_IsSubEventSupported
ValkeyModule_KeyAtPos
ValkeyModule_KeyAtPosWithFlags
ValkeyModule_KeyExists
ValkeyModule_KeyType
ValkeyModule_KillForkChild
ValkeyModule_LatencyAddSample
ValkeyModule_ListDelete
ValkeyModule_ListGet
ValkeyModule_ListInsert
ValkeyModule_ListPop
ValkeyModule_ListPush
ValkeyModule_ListSet
ValkeyModule_LoadConfigs
ValkeyModule_LoadDataTypeFromString
ValkeyModule_LoadDataTypeFromStringEncver
ValkeyModule_LoadDouble
ValkeyModule_LoadFloat
ValkeyModule_LoadLongDouble
ValkeyModule_LoadSigned
ValkeyModule_LoadString
ValkeyModule_LoadStringBuffer
ValkeyModule_LoadUnsigned
ValkeyModule_Log
ValkeyModule_LogIOError
ValkeyModule_MallocSize
ValkeyModule_MallocSizeDict
ValkeyModule_MallocSizeString
ValkeyModule_MallocUsableSize
ValkeyModule_Microseconds
ValkeyModule_Milliseconds
ValkeyModule_ModuleTypeGetType
ValkeyModule_ModuleTypeGetValue
ValkeyModule_ModuleTypeReplaceValue
ValkeyModule_ModuleTypeSetValue
ValkeyModule_MonotonicMicroseconds
ValkeyModule_MustObeyClient
ValkeyModule_NotifyKeyspaceEvent
ValkeyModule_OpenKey
ValkeyModule_PoolAlloc
ValkeyModule_PublishMessage
ValkeyModule_PublishMessageShard
ValkeyModule_RandomKey
ValkeyModule_RdbLoad
ValkeyModule_RdbSave
ValkeyModule_RdbStreamCreateFromFile
ValkeyModule_RdbStreamFree
ValkeyModule_Realloc
ValkeyModule_RedactClientCommandArgument
ValkeyModule_RegisterAuthCallback
ValkeyModule_RegisterBoolConfig
ValkeyModule_RegisterClusterMessageReceiver
ValkeyModule_RegisterCommandFilter
ValkeyModule_RegisterDefragFunc
ValkeyModule_RegisterEnumConfig
ValkeyModule_RegisterInfoFunc
ValkeyModule_RegisterNumericConfig
ValkeyModule_RegisterScriptingEngine
ValkeyModule_RegisterStringConfig
ValkeyModule_Replicate
ValkeyModule_ReplicateVerbatim
ValkeyModule_ReplySetArrayLength
如果
ValkeyModule_ReplyWithAttribute
返回错误,则不得调用此函数。ValkeyModule_ReplySetMapLength
ValkeyModule_ReplySetSetLength
ValkeyModule_ReplyWithArray
ValkeyModule_ReplyWithAttribute
ValkeyModule_ReplyWithBigNumber
ValkeyModule_ReplyWithBool
ValkeyModule_ReplyWithCString
ValkeyModule_ReplyWithCallReply
ValkeyModule_ReplyWithDouble
ValkeyModule_ReplyWithEmptyArray
ValkeyModule_ReplyWithEmptyString
ValkeyModule_ReplyWithError
ValkeyModule_ReplyWithErrorFormat
ValkeyModule_ReplyWithLongDouble
ValkeyModule_ReplyWithLongLong
ValkeyModule_ReplyWithMap
ValkeyModule_ReplyWithNull
ValkeyModule_ReplyWithNullArray
ValkeyModule_ReplyWithSet
ValkeyModule_ReplyWithSimpleString
ValkeyModule_ReplyWithString
ValkeyModule_ReplyWithStringBuffer
ValkeyModule_ReplyWithVerbatimString
ValkeyModule_ReplyWithVerbatimStringType
ValkeyModule_ResetDataset
ValkeyModule_RetainString
ValkeyModule_SaveDataTypeToString
ValkeyModule_SaveDouble
ValkeyModule_SaveFloat
ValkeyModule_SaveLongDouble
ValkeyModule_SaveSigned
ValkeyModule_SaveString
ValkeyModule_SaveStringBuffer
ValkeyModule_SaveUnsigned
ValkeyModule_Scan
ValkeyModule_ScanCursorCreate
ValkeyModule_ScanCursorDestroy
ValkeyModule_ScanCursorRestart
ValkeyModule_ScanKey
ValkeyModule_SelectDb
ValkeyModule_SendChildHeartbeat
ValkeyModule_SendClusterMessage
ValkeyModule_ServerInfoGetField
ValkeyModule_ServerInfoGetFieldC
ValkeyModule_ServerInfoGetFieldDouble
ValkeyModule_ServerInfoGetFieldSigned
ValkeyModule_ServerInfoGetFieldUnsigned
ValkeyModule_SetAbsExpire
ValkeyModule_SetClientNameById
ValkeyModule_SetClusterFlags
ValkeyModule_SetCommandACLCategories
ValkeyModule_SetCommandInfo
ValkeyModule_SetContextUser
ValkeyModule_SetDisconnectCallback
ValkeyModule_SetExpire
ValkeyModule_SetLFU
ValkeyModule_SetLRU
ValkeyModule_SetModuleOptions
ValkeyModule_SetModuleUserACL
ValkeyModule_SetModuleUserACLString
ValkeyModule_SignalKeyAsReady
ValkeyModule_SignalModifiedKey
ValkeyModule_StopTimer
ValkeyModule_Strdup
ValkeyModule_StreamAdd
ValkeyModule_StreamDelete
ValkeyModule_StreamIteratorDelete
ValkeyModule_StreamIteratorNextField
ValkeyModule_StreamIteratorNextID
ValkeyModule_StreamIteratorStart
ValkeyModule_StreamIteratorStop
ValkeyModule_StreamTrimByID
ValkeyModule_StreamTrimByLength
ValkeyModule_StringAppendBuffer
ValkeyModule_StringCompare
ValkeyModule_StringDMA
ValkeyModule_StringPtrLen
ValkeyModule_StringSet
ValkeyModule_StringToDouble
ValkeyModule_StringToLongDouble
ValkeyModule_StringToLongLong
ValkeyModule_StringToStreamID
ValkeyModule_StringToULongLong
ValkeyModule_StringTruncate
ValkeyModule_SubscribeToKeyspaceEvents
ValkeyModule_SubscribeToServerEvent
ValkeyModule_ThreadSafeContextLock
ValkeyModule_ThreadSafeContextTryLock
ValkeyModule_ThreadSafeContextUnlock
ValkeyModule_TrimStringAllocation
ValkeyModule_TryAlloc
ValkeyModule_TryCalloc
ValkeyModule_TryRealloc
ValkeyModule_UnblockClient
ValkeyModule_UnlinkKey
ValkeyModule_UnregisterCommandFilter
ValkeyModule_UnregisterScriptingEngine
ValkeyModule_UpdateRuntimeArgs
ValkeyModule_ValueLength
ValkeyModule_WrongArity
ValkeyModule_Yield
ValkeyModule_ZsetAdd
ValkeyModule_ZsetFirstInLexRange
ValkeyModule_ZsetFirstInScoreRange
ValkeyModule_ZsetIncrby
ValkeyModule_ZsetLastInLexRange
ValkeyModule_ZsetLastInScoreRange
ValkeyModule_ZsetRangeCurrentElement
ValkeyModule_ZsetRangeEndReached
ValkeyModule_ZsetRangeNext
ValkeyModule_ZsetRangePrev
ValkeyModule_ZsetRangeStop
ValkeyModule_ZsetRem
ValkeyModule_ZsetScore
ValkeyModule__Assert