模块 API 参考

Redis 模块 API 参考

章节

堆分配原始函数

使用这些函数分配的内存会被Redis的键淘汰算法考虑在内,并在Redis内存使用信息中报告。

RedisModule_Alloc

void *RedisModule_Alloc(size_t bytes);

自版本起可用: 4.0.0

使用方式类似于malloc()。使用此函数分配的内存会在Redis的INFO内存中报告,用于根据maxmemory设置进行键的驱逐,并且通常被视为Redis分配的内存。你应该避免使用malloc()。如果无法分配足够的内存,此函数会引发恐慌。

RedisModule_TryAlloc

void *RedisModule_TryAlloc(size_t bytes);

自版本起可用: 7.0.0

类似于RedisModule_Alloc,但在分配失败时返回NULL,而不是引发恐慌。

RedisModule_Calloc

void *RedisModule_Calloc(size_t nmemb, size_t size);

自版本起可用: 4.0.0

使用类似于calloc()。使用此函数分配的内存会在Redis INFO内存中报告,用于根据maxmemory设置进行键的驱逐,并且通常被视为由Redis分配的内存。你应该避免直接使用calloc()

RedisModule_TryCalloc

void *RedisModule_TryCalloc(size_t nmemb, size_t size);

自版本起可用: 7.4.0

类似于RedisModule_Calloc,但在分配失败时返回NULL,而不是引发恐慌。

RedisModule_Realloc

void* RedisModule_Realloc(void *ptr, size_t bytes);

自版本起可用: 4.0.0

使用类似于realloc()的函数来处理通过RedisModule_Alloc()获得的内存。

RedisModule_TryRealloc

void *RedisModule_TryRealloc(void *ptr, size_t bytes);

自版本起可用: 7.4.0

类似于RedisModule_Realloc,但在分配失败时返回NULL,而不是引发恐慌。

RedisModule_Free

void RedisModule_Free(void *ptr);

自版本起可用: 4.0.0

使用类似于 free() 的方式来释放通过 RedisModule_Alloc()RedisModule_Realloc() 获得的内存。然而,你永远不应该尝试使用 RedisModule_Free() 来释放模块内部使用 malloc() 分配的内存。

RedisModule_Strdup

char *RedisModule_Strdup(const char *str);

自版本起可用: 4.0.0

类似于 strdup(),但返回使用 RedisModule_Alloc() 分配的内存。

RedisModule_PoolAlloc

void *RedisModule_PoolAlloc(RedisModuleCtx *ctx, size_t bytes);

自版本起可用: 4.0.0

返回堆分配的内存,这些内存在模块回调函数返回时自动释放。主要适用于生命周期短且必须在回调返回时释放的小型分配。如果请求的字节数至少为架构字大小,则返回的内存与架构字大小对齐,否则与下一个二的幂对齐,例如,3字节的请求是4字节对齐,而2字节的请求是2字节对齐。

没有realloc风格的函数,因为当需要使用池分配器时,这并不是一个好主意。

如果bytes为0,函数返回NULL。

命令 API

这些函数用于实现自定义的Redis命令。

例如,参见 https://redis.io/topics/modules-intro

RedisModule_IsKeysPositionRequest

int RedisModule_IsKeysPositionRequest(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

如果以特殊方式调用使用“getkeys-api”标志声明的模块命令以获取键位置而不执行,则返回非零值。否则返回零。

RedisModule_KeyAtPosWithFlags

void RedisModule_KeyAtPosWithFlags(RedisModuleCtx *ctx, int pos, int flags);

自版本起可用: 7.0.0

当调用模块命令以获取键的位置时,由于在注册期间被标记为“getkeys-api”,命令实现使用RedisModule_IsKeysPositionRequest() API检查此特殊调用,并使用此函数来报告键。

支持的标志是RedisModule_SetCommandInfo使用的那些,请参阅REDISMODULE_CMD_KEY_*。

以下是一个如何使用它的示例:

if (RedisModule_IsKeysPositionRequest(ctx)) {
    RedisModule_KeyAtPosWithFlags(ctx, 2, REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_ACCESS);
    RedisModule_KeyAtPosWithFlags(ctx, 1, REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE | REDISMODULE_CMD_KEY_ACCESS);
}

注意:在上面的示例中,获取键的API本可以通过键规范(首选)来处理。 只有在无法声明覆盖所有键的键规范时,才需要实现getkeys-api。

RedisModule_KeyAtPos

void RedisModule_KeyAtPos(RedisModuleCtx *ctx, int pos);

自版本起可用: 4.0.0

此API在RedisModule_KeyAtPosWithFlags添加之前就已存在,现已弃用,可用于与旧版本的兼容性,在引入key-specs和flags之前。

RedisModule_IsChannelsPositionRequest

int RedisModule_IsChannelsPositionRequest(RedisModuleCtx *ctx);

自版本起可用: 7.0.0

如果以特殊方式调用声明为“getchannels-api”标志的模块命令以获取通道位置而不执行,则返回非零值。否则返回零。

RedisModule_ChannelAtPosWithFlags

void RedisModule_ChannelAtPosWithFlags(RedisModuleCtx *ctx,
                                       int pos,
                                       int flags);

自版本起可用: 7.0.0

当调用模块命令以获取通道位置时,由于在注册期间被标记为“getchannels-api”,命令实现使用RedisModule_IsChannelsPositionRequest() API检查此特殊调用,并使用此函数来报告通道。

支持的标志有:

  • REDISMODULE_CMD_CHANNEL_SUBSCRIBE: 此命令将订阅频道。
  • REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE: 此命令将取消订阅此频道。
  • REDISMODULE_CMD_CHANNEL_PUBLISH: 此命令将发布到此频道。
  • REDISMODULE_CMD_CHANNEL_PATTERN: 不是作用于特定频道,而是作用于由模式指定的任何频道。这与Redis中可用的PSUBSCRIBE和PUNSUBSCRIBE命令使用的访问权限相同。不打算与PUBLISH权限一起使用。

以下是一个如何使用它的示例:

if (RedisModule_IsChannelsPositionRequest(ctx)) {
    RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_SUBSCRIBE | REDISMODULE_CMD_CHANNEL_PATTERN);
    RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_PUBLISH);
}

注意:声明通道的一种用途是评估ACL权限。在这种情况下,取消订阅始终是允许的,因此命令只会针对订阅和发布权限进行检查。这比使用RedisModule_ACLCheckChannelPermissions更可取,因为它允许在执行命令之前检查ACL。

RedisModule_CreateCommand

int RedisModule_CreateCommand(RedisModuleCtx *ctx,
                              const char *name,
                              RedisModuleCmdFunc cmdfunc,
                              const char *strflags,
                              int firstkey,
                              int lastkey,
                              int keystep);

自版本起可用: 4.0.0

在Redis服务器中注册一个新命令,该命令将通过使用RedisModule调用约定调用函数指针'cmdfunc'来处理。

在这些情况下,函数返回 REDISMODULE_ERR

  • 如果在RedisModule_OnLoad之外调用模块命令的创建。
  • 指定的命令已经忙。
  • 命令名称包含一些不允许的字符。
  • 传递了一组无效的标志。

否则返回REDISMODULE_OK并注册新命令。

此函数必须在模块初始化期间在RedisModule_OnLoad()函数内部调用。在初始化函数之外调用此函数是未定义的。

命令函数类型如下:

 int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);

并且应该始终返回 REDISMODULE_OK

标志集 'strflags' 指定了命令的行为,应该作为一个由空格分隔的单词组成的C字符串传递,例如 "write deny-oom"。标志集包括:

  • "write": 该命令可能会修改数据集(也可能从中读取数据)。
  • "readonly": 该命令从键中返回数据,但从不写入。
  • "admin": 该命令是一个管理命令(可能会更改复制或执行类似任务)。
  • "deny-oom": 该命令可能会使用额外的内存,在内存不足的情况下应被拒绝。
  • "deny-script": 不允许在Lua脚本中使用此命令。
  • "allow-loading": 允许在服务器加载数据时执行此命令。 只有不与数据集交互的命令 才应允许在此模式下运行。如果不确定 请不要使用此标志。
  • "pubsub": 该命令在Pub/Sub频道上发布内容。
  • "random": 即使从相同的输入参数和键值开始,该命令也可能有不同的输出。 从Redis 7.0开始,此标志已被弃用。 可以使用命令提示将命令声明为"random",请参见https://redis.io/topics/command-tips
  • "allow-stale": 该命令允许在不提供过期数据的从服务器上运行。如果你不知道这是什么意思,请不要使用。
  • "no-monitor": 不要在监视器上传播命令。如果命令的参数中包含敏感数据,请使用此选项。
  • "no-slowlog": 不要在慢日志中记录此命令。如果命令的参数中包含敏感数据,请使用此选项。
  • "fast": 命令的时间复杂度不超过O(log(N)),其中N是集合的大小或任何其他表示命令正常可扩展性问题的内容。
  • "getkeys-api": 该命令实现了返回键参数的接口。当由于命令语法原因,start/stop/step 不够用时使用。
  • "no-cluster": 该命令不应在Redis集群中注册,因为它不是设计用于与集群一起工作的,例如,它无法报告键的位置,以编程方式创建键名,或任何其他原因。
  • "no-auth": 此命令可以由未经身份验证的客户端运行。 通常,这用于用于验证客户端身份的命令。
  • "may-replicate": 此命令可能会生成复制流量,即使它不是写命令。
  • "no-mandatory-keys": 此命令可能使用的所有键都是可选的
  • "blocking": 该命令有可能阻塞客户端。
  • "allow-busy": 允许在服务器被脚本或慢模块命令阻塞时执行该命令,参见 RedisModule_Yield。
  • "getchannels-api": 该命令实现了返回通道参数的接口。

最后三个参数指定了新命令的哪些参数是Redis键。更多信息请参见https://redis.io/commands/command

  • firstkey: 第一个作为键的参数的基于1的索引。 位置0始终是命令名称本身。 对于没有键的命令为0。
  • lastkey: 最后一个键参数的基于1的索引。 负数表示从最后一个参数开始倒数(-1表示提供的最后一个参数) 对于没有键的命令为0。
  • keystep: 第一个和最后一个键索引之间的步长。对于没有键的命令为0。

此信息由ACL、集群和COMMAND命令使用。

注意:上述方案用途有限,只能用于查找存在于固定索引的键。 对于非平凡的键参数,您可以传递0,0,0并使用 RedisModule_SetCommandInfo来设置键规范,使用更高级的方案,并使用 RedisModule_SetCommandACLCategories来设置命令的Redis ACL类别。

RedisModule_GetCommand

RedisModuleCommand *RedisModule_GetCommand(RedisModuleCtx *ctx,
                                           const char *name);

自版本起可用: 7.0.0

通过命令名称获取一个不透明的结构,表示模块命令。 此结构用于一些与命令相关的API中。

在以下错误情况下返回NULL:

  • 未找到命令
  • 该命令不是模块命令
  • 该命令不属于调用模块

RedisModule_CreateSubcommand

int RedisModule_CreateSubcommand(RedisModuleCommand *parent,
                                 const char *name,
                                 RedisModuleCmdFunc cmdfunc,
                                 const char *strflags,
                                 int firstkey,
                                 int lastkey,
                                 int keystep);

自版本起可用: 7.0.0

RedisModule_CreateCommand非常相似,不同之处在于它用于创建一个子命令,该子命令与另一个容器命令相关联。

示例:如果一个模块有一个配置命令,MODULE.CONFIG,那么 GET 和 SET 应该是单独的子命令,而 MODULE.CONFIG 是 一个命令,但不应注册为有效的 funcptr

 if (RedisModule_CreateCommand(ctx,"module.config",NULL,"",0,0,0) == REDISMODULE_ERR)
     return REDISMODULE_ERR;

 RedisModuleCommand *parent = RedisModule_GetCommand(ctx,,"module.config");

 if (RedisModule_CreateSubcommand(parent,"set",cmd_config_set,"",0,0,0) == REDISMODULE_ERR)
    return REDISMODULE_ERR;

 if (RedisModule_CreateSubcommand(parent,"get",cmd_config_get,"",0,0,0) == REDISMODULE_ERR)
    return REDISMODULE_ERR;

成功时返回 REDISMODULE_OK,在以下错误情况下返回 REDISMODULE_ERR

  • 解析 strflags 时出错
  • 命令被标记为no-cluster,但集群模式已启用
  • parent 已经是一个子命令(我们不允许超过一级的命令嵌套)
  • parent 是一个带有实现的命令 (RedisModuleCmdFunc)(父命令应该是子命令的纯容器)
  • parent 已经有一个名为 name 的子命令
  • 创建子命令是在RedisModule_OnLoad之外调用的。

RedisModule_AddACLCategory

int RedisModule_AddACLCategory(RedisModuleCtx *ctx, const char *name);

自版本起可用: 7.4.0

RedisModule_AddACLCategory 可用于添加新的ACL命令类别。类别名称只能包含字母数字字符、下划线或破折号。类别只能在RedisModule_OnLoad函数中添加。一旦添加了类别,就不能删除。任何模块都可以使用RedisModule_SetCommandACLCategories将命令注册到任何已添加的类别中。

返回:

  • REDISMODULE_OK 成功添加新的ACL类别。
  • REDISMODULE_ERR 失败时。

出错时,errno 被设置为:

  • 如果名称包含无效字符,则返回EINVAL。
  • 如果类别名称已经存在,则返回EBUSY。
  • ENOMEM 如果类别数量达到最大限制64个类别。

RedisModule_SetCommandACLCategories

int RedisModule_SetCommandACLCategories(RedisModuleCommand *command,
                                        const char *aclflags);

自版本起可用: 7.2.0

RedisModule_SetCommandACLCategories 可用于为模块命令和子命令设置ACL类别。ACL类别的集合应作为空格分隔的C字符串 'aclflags' 传递。

例如,acl标志'write slow'将命令标记为写入和慢速ACL类别的一部分。

成功时返回REDISMODULE_OK。出错时返回REDISMODULE_ERR

此函数只能在RedisModule_OnLoad函数期间调用。如果在此函数之外调用,将返回错误。

RedisModule_SetCommandInfo

int RedisModule_SetCommandInfo(RedisModuleCommand *command,
                               const RedisModuleCommandInfo *info);

自版本起可用: 7.0.0

设置额外的命令信息。

影响COMMANDCOMMAND INFOCOMMAND DOCS的输出,集群, ACL,并用于在调用到达模块代码之前过滤参数数量错误的命令。

此函数可以在使用RedisModule_CreateCommand创建命令并使用RedisModule_GetCommand获取命令指针后调用。每个命令的信息只能设置一次,并具有以下结构:

typedef struct RedisModuleCommandInfo {
    const RedisModuleCommandInfoVersion *version;
    const char *summary;
    const char *complexity;
    const char *since;
    RedisModuleCommandHistoryEntry *history;
    const char *tips;
    int arity;
    RedisModuleCommandKeySpec *key_specs;
    RedisModuleCommandArg *args;
} RedisModuleCommandInfo;

除了version字段外,所有字段都是可选的。字段的解释如下:

  • version: 此字段用于与不同版本的Redis兼容。 始终将此字段设置为REDISMODULE_COMMAND_INFO_VERSION

  • summary: 命令的简短描述(可选)。

  • complexity: 复杂度描述(可选)。

  • since: 命令引入的版本(可选)。 注意:指定的版本应该是模块的版本,而不是Redis的版本。

  • history: 一个RedisModuleCommandHistoryEntry数组(可选),它是一个包含以下字段的结构体:

      const char *since;
      const char *changes;
    

    since 是一个版本字符串,changes 是一个描述更改的字符串。数组以一个零值条目终止,即一个两个字符串都设置为NULL的条目。

  • tips: 一串空格分隔的提示,关于此命令,旨在为客户端和代理提供信息。参见 https://redis.io/topics/command-tips

  • arity: 参数的数量,包括命令名称本身。一个正数指定确切的参数数量,一个负数指定最小的参数数量,因此使用 -N 表示 >= N。Redis 在将调用传递给模块之前会进行验证,因此这可以替代模块命令实现中的参数数量检查。如果命令有子命令,则值为 0(或省略的 arity 字段)等同于 -2,否则等同于 -1。

  • key_specs: An array of RedisModuleCommandKeySpec, terminated by an element memset to zero. This is a scheme that tries to describe the positions of key arguments better than the old RedisModule_CreateCommand arguments firstkey, lastkey, keystep and is needed if those three are not enough to describe the key positions. There are two steps to retrieve key positions: begin search (BS) in which index should find the first key and find keys (FK) which, relative to the output of BS, describes how can we will which arguments are keys. Additionally, there are key specific flags.

    Key-specs cause the triplet (firstkey, lastkey, keystep) given in RedisModule_CreateCommand to be recomputed, but it is still useful to provide these three parameters in RedisModule_CreateCommand, to better support old Redis versions where RedisModule_SetCommandInfo is not available.

    Note that key-specs don't fully replace the "getkeys-api" (see RedisModule_CreateCommand, RedisModule_IsKeysPositionRequest and RedisModule_KeyAtPosWithFlags) so it may be a good idea to supply both key-specs and implement the getkeys-api.

    A key-spec has the following structure:

      typedef struct RedisModuleCommandKeySpec {
          const char *notes;
          uint64_t flags;
          RedisModuleKeySpecBeginSearchType begin_search_type;
          union {
              struct {
                  int pos;
              } index;
              struct {
                  const char *keyword;
                  int startfrom;
              } keyword;
          } bs;
          RedisModuleKeySpecFindKeysType find_keys_type;
          union {
              struct {
                  int lastkey;
                  int keystep;
                  int limit;
              } range;
              struct {
                  int keynumidx;
                  int firstkey;
                  int keystep;
              } keynum;
          } fk;
      } RedisModuleCommandKeySpec;
    

    Explanation of the fields of RedisModuleCommandKeySpec:

    • notes: Optional notes or clarifications about this key spec.

    • flags: A bitwise or of key-spec flags described below.

    • begin_search_type: This describes how the first key is discovered. There are two ways to determine the first key:

      • REDISMODULE_KSPEC_BS_UNKNOWN: There is no way to tell where the key args start.
      • REDISMODULE_KSPEC_BS_INDEX: Key args start at a constant index.
      • REDISMODULE_KSPEC_BS_KEYWORD: Key args start just after a specific keyword.
    • bs: This is a union in which the index or keyword branch is used depending on the value of the begin_search_type field.

      • bs.index.pos: The index from which we start the search for keys. (REDISMODULE_KSPEC_BS_INDEX only.)

      • bs.keyword.keyword: The keyword (string) that indicates the beginning of key arguments. (REDISMODULE_KSPEC_BS_KEYWORD only.)

      • bs.keyword.startfrom: An index in argv from which to start searching. Can be negative, which means start search from the end, in reverse. Example: -2 means to start in reverse from the penultimate argument. (REDISMODULE_KSPEC_BS_KEYWORD only.)

    • find_keys_type: After the "begin search", this describes which arguments are keys. The strategies are:

      • REDISMODULE_KSPEC_BS_UNKNOWN: There is no way to tell where the key args are located.
      • REDISMODULE_KSPEC_FK_RANGE: Keys end at a specific index (or relative to the last argument).
      • REDISMODULE_KSPEC_FK_KEYNUM: There's an argument that contains the number of key args somewhere before the keys themselves.

      find_keys_type and fk can be omitted if this keyspec describes exactly one key.

    • fk: This is a union in which the range or keynum branch is used depending on the value of the find_keys_type field.

      • fk.range (for REDISMODULE_KSPEC_FK_RANGE): A struct with the following fields:

        • lastkey: Index of the last key relative to the result of the begin search step. Can be negative, in which case it's not relative. -1 indicates the last argument, -2 one before the last and so on.

        • keystep: How many arguments should we skip after finding a key, in order to find the next one?

        • limit: If lastkey is -1, we use limit to stop the search by a factor. 0 and 1 mean no limit. 2 means 1/2 of the remaining args, 3 means 1/3, and so on.

      • fk.keynum (for REDISMODULE_KSPEC_FK_KEYNUM): A struct with the following fields:

        • keynumidx: Index of the argument containing the number of keys to come, relative to the result of the begin search step.

        • firstkey: Index of the fist key relative to the result of the begin search step. (Usually it's just after keynumidx, in which case it should be set to keynumidx + 1.)

        • keystep: How many arguments should we skip after finding a key, in order to find the next one?

    Key-spec flags:

    The first four refer to what the command actually does with the value or metadata of the key, and not necessarily the user data or how it affects it. Each key-spec may must have exactly one of these. Any operation that's not distinctly deletion, overwrite or read-only would be marked as RW.

    • REDISMODULE_CMD_KEY_RO: Read-Only. Reads the value of the key, but doesn't necessarily return it.

    • REDISMODULE_CMD_KEY_RW: Read-Write. Modifies the data stored in the value of the key or its metadata.

    • REDISMODULE_CMD_KEY_OW: Overwrite. Overwrites the data stored in the value of the key.

    • REDISMODULE_CMD_KEY_RM: Deletes the key.

    The next four refer to user data inside the value of the key, not the metadata like LRU, type, cardinality. It refers to the logical operation on the user's data (actual input strings or TTL), being used/returned/copied/changed. It doesn't refer to modification or returning of metadata (like type, count, presence of data). ACCESS can be combined with one of the write operations INSERT, DELETE or UPDATE. Any write that's not an INSERT or a DELETE would be UPDATE.

    • REDISMODULE_CMD_KEY_ACCESS: Returns, copies or uses the user data from the value of the key.

    • REDISMODULE_CMD_KEY_UPDATE: Updates data to the value, new value may depend on the old value.

    • REDISMODULE_CMD_KEY_INSERT: Adds data to the value with no chance of modification or deletion of existing data.

    • REDISMODULE_CMD_KEY_DELETE: Explicitly deletes some content from the value of the key.

    Other flags:

    • REDISMODULE_CMD_KEY_NOT_KEY: The key is not actually a key, but should be routed in cluster mode as if it was a key.

    • REDISMODULE_CMD_KEY_INCOMPLETE: The keyspec might not point out all the keys it should cover.

    • REDISMODULE_CMD_KEY_VARIABLE_FLAGS: Some keys might have different flags depending on arguments.

  • args: 一个由RedisModuleCommandArg组成的数组,以一个被memset为零的元素结束。RedisModuleCommandArg是一个结构体,包含以下描述的字段。

      typedef struct RedisModuleCommandArg {
          const char *name;
          RedisModuleCommandArgType type;
          int key_spec_index;
          const char *token;
          const char *summary;
          const char *since;
          int flags;
          struct RedisModuleCommandArg *subargs;
      } RedisModuleCommandArg;
    

    字段的解释:

    • name: 参数的名称。

    • type: 参数的类型。详见下文。类型REDISMODULE_ARG_TYPE_ONEOFREDISMODULE_ARG_TYPE_BLOCK要求参数具有子参数,即subargs

    • key_spec_index: 如果typeREDISMODULE_ARG_TYPE_KEY,你必须提供与此参数关联的key-spec的索引。参见上面的key_specs。如果参数不是key,你可以指定-1。

    • token: 参数前面的标记(可选)。例如:SET中的参数seconds有一个标记EX。如果参数仅由一个标记组成(例如SET中的NX),类型应为REDISMODULE_ARG_TYPE_PURE_TOKEN,且value应为NULL。

    • summary: 参数的简短描述(可选)。

    • since: 包含此参数的第一个版本(可选)。

    • flags: 宏REDISMODULE_CMD_ARG_*的位或。详见下文。

    • value: 参数的显示值。这个字符串应该是从COMMAND的输出创建命令语法时显示的。如果token不为NULL,它也应该被显示。

    RedisModuleCommandArgType的解释:

    • REDISMODULE_ARG_TYPE_STRING: 字符串参数。
    • REDISMODULE_ARG_TYPE_INTEGER: 整数参数。
    • REDISMODULE_ARG_TYPE_DOUBLE: 双精度浮点数参数。
    • REDISMODULE_ARG_TYPE_KEY: 表示键名的字符串参数。
    • REDISMODULE_ARG_TYPE_PATTERN: 字符串,但为正则表达式模式。
    • REDISMODULE_ARG_TYPE_UNIX_TIME: 整数,但为Unix时间戳。
    • REDISMODULE_ARG_TYPE_PURE_TOKEN: 参数没有占位符。它只是一个没有值的标记。例如:SET命令中的KEEPTTL选项。
    • REDISMODULE_ARG_TYPE_ONEOF: 当用户只能从几个子参数中选择一个时使用。需要subargs。例如:SET中的NXXX选项。
    • REDISMODULE_ARG_TYPE_BLOCK: 当想要将几个子参数组合在一起时使用,通常是为了对它们全部应用某些东西,比如使整个组“可选”。需要subargs。例如:ZRANGE中的LIMIT offset count参数。

    命令参数标志的解释:

    • REDISMODULE_CMD_ARG_OPTIONAL: 参数是可选的(如SET命令中的GET)。
    • REDISMODULE_CMD_ARG_MULTIPLE: 参数可以重复(如DEL中的key)。
    • REDISMODULE_CMD_ARG_MULTIPLE_TOKEN: 参数可以重复,其标记也可以重复(如SORT中的GET pattern)。

成功时返回REDISMODULE_OK。出错时返回REDISMODULE_ERR,并且如果提供了无效信息,errno会被设置为EINVAL,如果信息已经设置,则设置为EEXIST。如果信息无效,会记录一条警告,解释信息的哪一部分无效以及原因。

模块信息和时间测量

RedisModule_IsModuleNameBusy

int RedisModule_IsModuleNameBusy(const char *name);

自版本起可用: 4.0.3

如果模块名称被占用,则返回非零值。 否则返回零。

RedisModule_Milliseconds

mstime_t RedisModule_Milliseconds(void);

自版本起可用: 4.0.0

返回当前的UNIX时间,单位为毫秒。

RedisModule_MonotonicMicroseconds

uint64_t RedisModule_MonotonicMicroseconds(void);

自版本起可用: 7.0.0

返回相对于任意时间点的微秒计数器。

RedisModule_Microseconds

ustime_t RedisModule_Microseconds(void);

自版本起可用: 7.2.0

返回当前的UNIX时间,单位为微秒

RedisModule_CachedMicroseconds

ustime_t RedisModule_CachedMicroseconds(void);

自版本起可用: 7.2.0

返回缓存的UNIX时间,单位为微秒。 它在服务器定时任务中更新,并在执行命令之前更新。 这对于复杂的调用堆栈非常有用,例如一个命令导致键空间通知,导致模块执行RedisModule_Call,导致另一个通知等。 所有这些回调使用相同的时钟是有意义的。

RedisModule_BlockedClientMeasureTimeStart

int RedisModule_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc);

自版本起可用: 6.2.0

标记一个时间点,该时间点将用作计算经过的执行时间的起始时间,当调用RedisModule_BlockedClientMeasureTimeEnd()时。在同一命令中,您可以多次调用RedisModule_BlockedClientMeasureTimeStart()RedisModule_BlockedClientMeasureTimeEnd(),以将独立的时间间隔累积到后台持续时间中。此方法始终返回REDISMODULE_OK

此函数不是线程安全的,如果在模块线程和阻塞回调(可能是主线程)中同时使用,建议使用调用者拥有的锁来保护它们,而不是GIL。

RedisModule_BlockedClientMeasureTimeEnd

int RedisModule_BlockedClientMeasureTimeEnd(RedisModuleBlockedClient *bc);

自版本起可用: 6.2.0

标记一个时间点,该时间点将用作计算已用执行时间的结束时间。 成功时返回REDISMODULE_OK。 如果之前没有定义开始时间(意味着没有调用RedisModule_BlockedClientMeasureTimeStart),则此方法仅返回REDISMODULE_ERR

此函数不是线程安全的,如果在模块线程和阻塞回调(可能是主线程)中同时使用,建议使用调用者拥有的锁来保护它们,而不是GIL。

RedisModule_Yield

void RedisModule_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply);

自版本起可用: 7.0.0

此API允许模块让Redis处理后台任务,以及在模块命令长时间阻塞执行期间处理一些命令。 模块可以定期调用此API。 flags是这些的位掩码:

  • REDISMODULE_YIELD_FLAG_NONE: 没有特殊标志,可以执行一些后台操作,但不能处理客户端命令。
  • REDISMODULE_YIELD_FLAG_CLIENTS: Redis 也可以处理客户端命令。

busy_reply 参数是可选的,可用于控制在 -BUSY 错误代码后的详细错误字符串。

当使用REDISMODULE_YIELD_FLAG_CLIENTS时,Redis只会在由busy-reply-threshold配置定义的时间后开始处理客户端命令,在这种情况下,Redis将开始拒绝大多数命令并返回-BUSY错误,但允许标记有allow-busy标志的命令被执行。 此API也可在线程安全上下文中使用(在锁定时),以及在加载期间使用(在rdb_load回调中,在这种情况下,它将拒绝命令并返回-LOADING错误)

RedisModule_SetModuleOptions

void RedisModule_SetModuleOptions(RedisModuleCtx *ctx, int options);

自版本起可用: 6.0.0

设置定义能力或行为的位标志。

REDISMODULE_OPTIONS_HANDLE_IO_ERRORS: 通常,模块不需要为此烦恼,因为如果发生读取错误,进程将直接终止,但是,设置此标志将允许在启用时使用无盘复制加载。 模块应在读取后使用RedisModule_IsIOError,在使用读取的数据之前,如果发生错误,应向上传播错误,并且能够释放部分填充的值及其所有分配。

REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED: 参见 RedisModule_SignalModifiedKey().

REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD: 设置此标志表示模块对无盘异步复制(repl-diskless-load=swapdb)的感知, 并且Redis可以在复制期间提供读取服务,而不是在LOADING状态下阻塞。

REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS: 声明模块希望获取嵌套的键空间通知。 默认情况下,Redis不会在键空间通知回调中触发键空间通知。此标志允许更改此行为并触发嵌套的键空间通知。注意:如果启用,模块应保护自己免受无限递归的影响。

RedisModule_SignalModifiedKey

int RedisModule_SignalModifiedKey(RedisModuleCtx *ctx,
                                  RedisModuleString *keyname);

自版本起可用: 6.0.0

表示从用户的角度来看,键已被修改(即使WATCH和客户端缓存失效)。

当以写入模式打开的键被关闭时,这是自动完成的,除非已经使用RedisModule_SetModuleOptions()设置了选项REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED

模块的自动内存管理

RedisModule_AutoMemory

void RedisModule_AutoMemory(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

启用自动内存管理。

该函数必须作为想要使用自动内存的命令实现的第一个函数调用。

启用后,自动内存管理会跟踪并在命令返回后自动释放键、调用回复和Redis字符串对象。在大多数情况下,这消除了调用以下函数的必要性:

  1. RedisModule_CloseKey()
  2. RedisModule_FreeCallReply()
  3. RedisModule_FreeString()

这些函数仍然可以在启用自动内存管理的情况下使用,例如优化进行大量分配的循环。

字符串对象 API

RedisModule_CreateString

RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx,
                                            const char *ptr,
                                            size_t len);

自版本起可用: 4.0.0

创建一个新的模块字符串对象。返回的字符串必须使用RedisModule_FreeString()释放,除非启用了自动内存管理。

字符串是通过从ptr开始复制len字节来创建的。不会保留对传递的缓冲区的引用。

模块上下文 'ctx' 是可选的,如果您想在上下文范围之外创建字符串,则可以为 NULL。然而,在这种情况下,自动内存管理将不可用,字符串内存必须手动管理。

RedisModule_CreateStringPrintf

RedisModuleString *RedisModule_CreateStringPrintf(RedisModuleCtx *ctx,
                                                  const char *fmt,
                                                  ...);

自版本起可用: 4.0.0

从printf格式和参数创建一个新的模块字符串对象。 返回的字符串必须使用RedisModule_FreeString()释放,除非启用了自动内存管理。

字符串是使用sds格式化函数sdscatvprintf()创建的。

如果需要,传递的上下文 'ctx' 可能为 NULL,更多信息请参阅 RedisModule_CreateString() 文档。

RedisModule_CreateStringFromLongLong

RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx,
                                                        long long ll);

自版本起可用: 4.0.0

类似于 RedisModule_CreateString(),但是从一个 long long 整数开始创建字符串,而不是接收一个缓冲区及其长度。

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

如果需要,传递的上下文 'ctx' 可能为 NULL,更多信息请参阅 RedisModule_CreateString() 文档。

RedisModule_CreateStringFromULongLong

RedisModuleString *RedisModule_CreateStringFromULongLong(RedisModuleCtx *ctx,
                                                         unsigned long long ull);

自版本起可用: 7.0.3

类似于 RedisModule_CreateString(),但是从一个 unsigned long long 整数开始创建字符串,而不是从缓冲区及其长度开始。

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

如果需要,传递的上下文 'ctx' 可能为 NULL,更多信息请参阅 RedisModule_CreateString() 文档。

RedisModule_CreateStringFromDouble

RedisModuleString *RedisModule_CreateStringFromDouble(RedisModuleCtx *ctx,
                                                      double d);

自版本起可用: 6.0.0

类似于 RedisModule_CreateString(),但是从一个双精度数开始创建字符串,而不是接收一个缓冲区及其长度。

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

RedisModule_CreateStringFromLongDouble

RedisModuleString *RedisModule_CreateStringFromLongDouble(RedisModuleCtx *ctx,
                                                          long double ld,
                                                          int humanfriendly);

自版本起可用: 6.0.0

类似于 RedisModule_CreateString(),但是从长双精度浮点数开始创建一个字符串。

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

如果需要,传递的上下文 'ctx' 可能为 NULL,更多信息请参阅 RedisModule_CreateString() 文档。

RedisModule_CreateStringFromString

RedisModuleString *RedisModule_CreateStringFromString(RedisModuleCtx *ctx,
                                                      const RedisModuleString *str);

自版本起可用: 4.0.0

类似于 RedisModule_CreateString(),但是从另一个 RedisModuleString 开始创建一个字符串。

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

如果需要,传递的上下文 'ctx' 可能为 NULL,更多信息请参阅 RedisModule_CreateString() 文档。

RedisModule_CreateStringFromStreamID

RedisModuleString *RedisModule_CreateStringFromStreamID(RedisModuleCtx *ctx,
                                                        const RedisModuleStreamID *id);

自版本起可用: 6.2.0

从流ID创建一个字符串。返回的字符串必须使用 RedisModule_FreeString()释放,除非启用了自动内存管理。

如果需要,传递的上下文 ctx 可能为 NULL。有关更多信息,请参阅 RedisModule_CreateString() 文档。

RedisModule_FreeString

void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str);

自版本起可用: 4.0.0

释放通过Redis模块API调用获得的新字符串对象的模块字符串对象。

即使在启用了自动内存管理的情况下,也可以调用此函数。在这种情况下,字符串将尽快被释放,并从要在结束时释放的字符串池中移除。

如果字符串是用NULL上下文'ctx'创建的,那么在释放字符串时也可以将ctx传递为NULL(但传递上下文不会产生任何问题)。使用上下文创建的字符串也应该通过传递上下文来释放,因此如果您希望稍后在上下文之外释放字符串,请确保使用NULL上下文创建它。

此API不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在GIL锁定的情况下进行。

RedisModule_RetainString

void RedisModule_RetainString(RedisModuleCtx *ctx, RedisModuleString *str);

自版本起可用: 4.0.0

每次调用此函数,都会使字符串 'str' 需要额外调用一次 RedisModule_FreeString() 才能真正释放该字符串。请注意,启用模块自动内存管理所获得的字符串自动释放算作一次 RedisModule_FreeString() 调用(它只是自动执行)。

通常,当以下条件同时为真时,您希望调用此函数:

  1. 您已启用自动内存管理。
  2. 你想要创建字符串对象。
  3. 你创建的这些字符串对象需要在创建它们的回调函数(例如命令实现)返回后继续存在。

通常你希望这样做是为了将创建的字符串对象存储到你自己的数据结构中,例如在实现新的数据类型时。

请注意,当内存管理关闭时,您不需要调用RetainString(),因为创建字符串将始终导致在回调函数返回后字符串仍然存在,如果没有执行FreeString()调用。

可以使用NULL上下文调用此函数。

当字符串将被长时间保留时,最好也调用RedisModule_TrimStringAllocation()以优化内存使用。

引用其他线程保留字符串的线程模块必须在字符串被保留后立即显式地修剪分配。不这样做可能会导致自动修剪,这不是线程安全的。

此API不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在GIL锁定的情况下进行。

RedisModule_HoldString

RedisModuleString* RedisModule_HoldString(RedisModuleCtx *ctx,
                                          RedisModuleString *str);

自版本起可用: 6.0.7

此函数可以代替RedisModule_RetainString()使用。 两者之间的主要区别在于此函数总是会成功,而RedisModule_RetainString()可能会因为断言而失败。

该函数返回一个指向RedisModuleString的指针,该指针由调用者拥有。当上下文的自动内存管理被禁用时,需要调用RedisModule_FreeString()来释放字符串。当自动内存管理启用时,您可以调用RedisModule_FreeString()或让自动化释放它。

这个函数比RedisModule_CreateStringFromString()更高效,因为只要有可能,它就会避免复制底层的RedisModuleString。使用这个函数的缺点是,可能无法在返回的RedisModuleString上使用RedisModule_StringAppendBuffer()

可以使用NULL上下文调用此函数。

当字符串将被长时间持有时,最好也调用RedisModule_TrimStringAllocation()以优化内存使用。

引用其他线程持有的字符串的线程模块必须在字符串被持有后立即显式地修剪分配。不这样做可能会导致自动修剪,这不是线程安全的。

此API不是线程安全的,访问这些保留的字符串(如果它们源自客户端命令参数)必须在GIL锁定的情况下进行。

RedisModule_StringPtrLen

const char *RedisModule_StringPtrLen(const RedisModuleString *str,
                                     size_t *len);

自版本起可用: 4.0.0

给定一个字符串模块对象,此函数返回字符串指针和字符串的长度。返回的指针和长度应仅用于只读访问,切勿修改。

RedisModule_StringToLongLong

int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll);

自版本起可用: 4.0.0

将字符串转换为long long整数,并将其存储在*ll中。 成功时返回REDISMODULE_OK。如果字符串无法解析为有效的、严格的long long(前后没有空格),则返回REDISMODULE_ERR

RedisModule_StringToULongLong

int RedisModule_StringToULongLong(const RedisModuleString *str,
                                  unsigned long long *ull);

自版本起可用: 7.0.3

将字符串转换为unsigned long long整数,并将其存储在*ull中。 成功时返回REDISMODULE_OK。如果字符串无法解析为有效的、严格的unsigned long long(前后没有空格),则返回REDISMODULE_ERR

RedisModule_StringToDouble

int RedisModule_StringToDouble(const RedisModuleString *str, double *d);

自版本起可用: 4.0.0

将字符串转换为双精度浮点数,并将其存储在*d中。 如果字符串不是有效的双精度浮点数表示,则返回REDISMODULE_OK表示成功,或返回REDISMODULE_ERR

RedisModule_StringToLongDouble

int RedisModule_StringToLongDouble(const RedisModuleString *str,
                                   long double *ld);

自版本起可用: 6.0.0

将字符串转换为长双精度浮点数,并将其存储在*ld中。 如果字符串不是有效的双精度浮点数表示,则返回REDISMODULE_OK表示成功,或返回REDISMODULE_ERR

RedisModule_StringToStreamID

int RedisModule_StringToStreamID(const RedisModuleString *str,
                                 RedisModuleStreamID *id);

自版本起可用: 6.2.0

将字符串转换为流ID,并将其存储在*id中。 成功时返回REDISMODULE_OK,如果字符串不是有效的流ID字符串表示形式,则返回REDISMODULE_ERR。允许使用特殊ID“+”和“-”。

RedisModule_StringCompare

int RedisModule_StringCompare(const RedisModuleString *a,
                              const RedisModuleString *b);

自版本起可用: 4.0.0

比较两个字符串对象,如果 a < b 返回 -1,如果 a == b 返回 0,如果 a > b 返回 1。字符串作为两个二进制数据块逐字节比较,不考虑任何编码或排序规则。

RedisModule_StringAppendBuffer

int RedisModule_StringAppendBuffer(RedisModuleCtx *ctx,
                                   RedisModuleString *str,
                                   const char *buf,
                                   size_t len);

自版本起可用: 4.0.0

将指定的缓冲区附加到字符串'str'。该字符串必须是用户创建的且仅被引用一次的字符串,否则返回REDISMODULE_ERR并且不执行操作。

RedisModule_TrimStringAllocation

void RedisModule_TrimStringAllocation(RedisModuleString *str);

自版本起可用: 7.0.0

修剪可能为RedisModuleString分配的过多内存。

有时,一个RedisModuleString可能会分配比所需更多的内存,通常用于从网络缓冲区构建的argv参数。此函数通过重新分配它们的内存来优化这些字符串,这对于那些不是短暂存在而是长时间保留的字符串非常有用。

此操作不是线程安全的,应仅在保证没有并发访问字符串时调用。在模块命令中使用它来处理argv字符串,在字符串可能对其他线程可用之前通常是安全的。

目前,当模块命令返回时,Redis 也可能自动修剪保留的字符串。然而,显式地执行此操作仍然应该是首选选项:

  1. Redis的未来版本可能会放弃自动修剪功能。
  2. 当前实现的自动修剪功能不是线程安全的。 一个后台线程操作最近保留的字符串可能会与自动修剪发生竞争条件,这可能导致数据损坏。

回复API

这些函数用于向客户端发送回复。

大多数函数总是返回REDISMODULE_OK,因此你可以将其与'return'一起使用,以便从命令实现中返回:

if (... some condition ...)
    return RedisModule_ReplyWithLongLong(ctx,mycount);

使用集合函数回复

在启动集合回复后,模块必须调用其他ReplyWith*样式的函数以发出集合的元素。集合类型包括:数组、映射、集合和属性。

当生成一个元素数量事先未知的集合时,可以使用一个特殊的标志REDISMODULE_POSTPONED_LEN(过去称为REDISMODULE_POSTPONED_ARRAY_LEN)来调用该函数,实际的元素数量可以在稍后通过RedisModule_ReplySet*Length()调用来设置(如果有多个“开放”计数,它将设置最新的一个)。

RedisModule_WrongArity

int RedisModule_WrongArity(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

发送一个关于提供给命令的参数数量的错误,在错误消息中引用命令名称。返回REDISMODULE_OK

示例:

if (argc != 3) return RedisModule_WrongArity(ctx);

RedisModule_ReplyWithLongLong

int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll);

自版本起可用: 4.0.0

向客户端发送一个整数回复,带有指定的long long值。 该函数总是返回REDISMODULE_OK

RedisModule_ReplyWithError

int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err);

自版本起可用: 4.0.0

回复错误 'err'。

请注意,'err' 必须包含所有错误信息,包括初始错误代码。该函数仅提供初始的 "-",因此使用方式如下:

RedisModule_ReplyWithError(ctx,"ERR Wrong Type");

而不仅仅是:

RedisModule_ReplyWithError(ctx,"Wrong Type");

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithErrorFormat

int RedisModule_ReplyWithErrorFormat(RedisModuleCtx *ctx,
                                     const char *fmt,
                                     ...);

自版本起可用: 7.2.0

使用printf格式和参数创建的错误进行回复。

请注意,'fmt' 必须包含所有错误信息,包括初始错误代码。该函数仅提供初始的 "-",因此使用方式如下:

RedisModule_ReplyWithErrorFormat(ctx,"ERR Wrong Type: %s",type);

而不仅仅是:

RedisModule_ReplyWithErrorFormat(ctx,"Wrong Type: %s",type);

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithSimpleString

int RedisModule_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg);

自版本起可用: 4.0.0

回复一个简单的字符串(在RESP协议中为+... \r\n)。这种回复仅适用于发送小的非二进制字符串且开销较小的情况,如“OK”或类似的回复。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithArray

int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len);

自版本起可用: 4.0.0

回复一个包含'len'个元素的数组类型。

在启动数组回复后,模块必须调用len次其他ReplyWith*风格的函数以发出数组的元素。更多详情请参阅回复API部分。

使用RedisModule_ReplySetArrayLength()来设置延迟长度。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithMap

int RedisModule_ReplyWithMap(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

回复一个包含'len'对的RESP3 Map类型。 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取更多关于RESP3的信息。

启动地图回复后,模块必须进行len*2次调用其他ReplyWith*风格的函数,以发出地图的元素。更多详情请参阅回复API部分。

如果连接的客户端使用的是RESP2,回复将被转换为一个扁平数组。

使用 RedisModule_ReplySetMapLength() 来设置延迟长度。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithSet

int RedisModule_ReplyWithSet(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

回复一个包含'len'个元素的RESP3集合类型。 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取更多关于RESP3的信息。

在启动一个集合回复后,模块必须调用len次其他ReplyWith*风格的函数以发出集合的元素。更多详情请参见回复API部分。

如果连接的客户端使用RESP2,回复将被转换为数组类型。

使用 RedisModule_ReplySetSetLength() 来设置延迟长度。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithAttribute

int RedisModule_ReplyWithAttribute(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

向回复添加属性(元数据)。应该在添加实际回复之前完成。参见 https://github.com/antirez/RESP3/blob/master/spec.md#attribute-type

在启动属性的回复后,模块必须进行len*2次调用其他ReplyWith*风格的函数,以发出属性映射的元素。更多详情请参阅回复API部分。

使用 RedisModule_ReplySetAttributeLength() 来设置延迟长度。

RESP2 不支持,将返回 REDISMODULE_ERR,否则 该函数始终返回 REDISMODULE_OK

RedisModule_ReplyWithNullArray

int RedisModule_ReplyWithNullArray(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

向客户端回复一个空数组,在RESP3中简单地返回null,在RESP2中返回空数组。

注意:在RESP3中,Null回复和NullArray回复没有区别,因此为了避免歧义,最好避免使用此API,而是使用RedisModule_ReplyWithNull

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithEmptyArray

int RedisModule_ReplyWithEmptyArray(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

向客户端回复一个空数组。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplySetArrayLength

void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len);

自版本起可用: 4.0.0

当使用RedisModule_ReplyWithArray()并带有参数REDISMODULE_POSTPONED_LEN时,因为我们事先不知道将要输出作为数组元素的项数,此函数将负责设置数组长度。

由于可能有多个长度未知的数组回复待处理,此函数保证始终以延迟方式设置最新创建的数组长度。

例如,为了输出像 [1,[10,20,30]] 这样的数组,我们可以这样写:

 RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
 RedisModule_ReplyWithLongLong(ctx,1);
 RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);
 RedisModule_ReplyWithLongLong(ctx,10);
 RedisModule_ReplyWithLongLong(ctx,20);
 RedisModule_ReplyWithLongLong(ctx,30);
 RedisModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.
 RedisModule_ReplySetArrayLength(ctx,2); // Set len of top array

请注意,在上面的示例中,没有理由推迟数组长度的确定,因为我们生成了固定数量的元素,但在实际应用中,代码可能会使用迭代器或其他生成输出的方式,因此很难提前计算元素的数量。

RedisModule_ReplySetMapLength

void RedisModule_ReplySetMapLength(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

RedisModule_ReplySetArrayLength非常相似,除了len应该是 在映射上下文中调用的ReplyWith*函数数量的一半。 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取有关RESP3的更多信息。

RedisModule_ReplySetSetLength

void RedisModule_ReplySetSetLength(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

RedisModule_ReplySetArrayLength非常相似 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取更多关于RESP3的信息。

RedisModule_ReplySetAttributeLength

void RedisModule_ReplySetAttributeLength(RedisModuleCtx *ctx, long len);

自版本起可用: 7.0.0

RedisModule_ReplySetMapLength非常相似 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取更多关于RESP3的信息。

如果RedisModule_ReplyWithAttribute返回错误,则不得调用。

RedisModule_ReplyWithStringBuffer

int RedisModule_ReplyWithStringBuffer(RedisModuleCtx *ctx,
                                      const char *buf,
                                      size_t len);

自版本起可用: 4.0.0

回复一个批量字符串,接收一个C缓冲区指针和长度作为输入。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithCString

int RedisModule_ReplyWithCString(RedisModuleCtx *ctx, const char *buf);

自版本起可用: 5.0.6

回复一个批量字符串,输入一个假设以空字符结尾的C缓冲区指针。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithString

int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);

自版本起可用: 4.0.0

回复一个批量字符串,输入一个RedisModuleString对象。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithEmptyString

int RedisModule_ReplyWithEmptyString(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

回复一个空字符串。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithVerbatimStringType

int RedisModule_ReplyWithVerbatimStringType(RedisModuleCtx *ctx,
                                            const char *buf,
                                            size_t len,
                                            const char *ext);

自版本起可用: 7.0.0

回复一个二进制安全字符串,该字符串不应被转义或过滤,输入一个C缓冲区指针、长度和一个3字符的类型/扩展名。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithVerbatimString

int RedisModule_ReplyWithVerbatimString(RedisModuleCtx *ctx,
                                        const char *buf,
                                        size_t len);

自版本起可用: 6.0.0

回复一个二进制安全字符串,该字符串不应被转义或过滤,输入一个C缓冲区指针和长度。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithNull

int RedisModule_ReplyWithNull(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

向客户端回复一个NULL。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithBool

int RedisModule_ReplyWithBool(RedisModuleCtx *ctx, int b);

自版本起可用: 7.0.0

回复一个RESP3布尔类型。 访问https://github.com/antirez/RESP3/blob/master/spec.md获取更多关于RESP3的信息。

在RESP3中,这是布尔类型 在RESP2中,它是分别表示真和假的字符串响应“1”和“0”。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithCallReply

int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx,
                                   RedisModuleCallReply *reply);

自版本起可用: 4.0.0

准确回复Redis命令通过RedisModule_Call()返回给我们的内容。 当我们使用RedisModule_Call()来执行某些命令时,这个函数非常有用,因为我们希望向客户端回复与命令获得的完全相同的回复。

返回:

  • REDISMODULE_OK 成功时。
  • REDISMODULE_ERR 如果给定的回复是 RESP3 格式,但客户端期望的是 RESP2。 在出现错误的情况下,模块编写者有责任将回复转换为 RESP2(或通过返回错误来处理)。请注意,为了方便模块编写者,可以将 0 作为参数传递给 RedisModule_Call 的 fmt 参数,以便 RedisModuleCallReply 将返回与当前客户端上下文中设置的相同协议(RESP2 或 RESP3)。

RedisModule_ReplyWithDouble

int RedisModule_ReplyWithDouble(RedisModuleCtx *ctx, double d);

自版本起可用: 4.0.0

回复一个RESP3 Double类型。 访问https://github.com/antirez/RESP3/blob/master/spec.md了解更多关于RESP3的信息。

发送一个通过将双精度浮点数'd'转换为批量字符串获得的字符串回复。 这个函数基本上等同于将双精度浮点数转换为字符串到C缓冲区,然后使用缓冲区和长度调用函数RedisModule_ReplyWithStringBuffer()

在RESP3中,字符串被标记为双精度类型,而在RESP2中,它只是一个普通的字符串,用户需要自行解析。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithBigNumber

int RedisModule_ReplyWithBigNumber(RedisModuleCtx *ctx,
                                   const char *bignum,
                                   size_t len);

自版本起可用: 7.0.0

回复一个RESP3 BigNumber类型。 访问https://github.com/antirez/RESP3/blob/master/spec.md以获取更多关于RESP3的信息。

在RESP3中,这是一个长度为len的字符串,被标记为大数(BigNumber), 然而,调用者有责任确保它是一个有效的大数。 在RESP2中,这只是一个普通的批量字符串响应。

该函数总是返回 REDISMODULE_OK

RedisModule_ReplyWithLongDouble

int RedisModule_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld);

自版本起可用: 6.0.0

发送一个通过将长双精度浮点数 'ld' 转换为批量字符串获得的字符串回复。这个函数基本上等同于将长双精度浮点数转换为字符串到C缓冲区中,然后使用缓冲区和长度调用函数 RedisModule_ReplyWithStringBuffer()。双精度字符串使用人类可读的格式(参见 networking.c 中的 addReplyHumanLongDouble)。

该函数总是返回 REDISMODULE_OK

命令复制API

RedisModule_Replicate

int RedisModule_Replicate(RedisModuleCtx *ctx,
                          const char *cmdname,
                          const char *fmt,
                          ...);

自版本起可用: 4.0.0

将指定的命令和参数复制到从服务器和AOF中,作为调用命令实现执行的效果。

复制的命令总是被包装在MULTI/EXEC中,这些命令按照它们执行的顺序包含在给定模块命令执行中复制的所有命令。

模块应尝试使用一个接口或另一个接口。

此命令遵循与RedisModule_Call()完全相同的接口, 因此必须传递一组格式说明符,然后是与提供的格式说明符匹配的参数。

请参考RedisModule_Call()获取更多信息。

使用特殊的 "A" 和 "R" 修饰符,调用者可以排除 AOF 或副本从指定命令的传播中。否则,默认情况下,命令将在两个通道中传播。

关于从线程安全上下文调用此函数的注意事项:

通常,当您从实现模块命令的回调或Redis模块API提供的任何其他回调中调用此函数时,Redis将在回调的上下文中累积对此函数的所有调用,并将所有命令包装在MULTI/EXEC事务中传播。然而,当从可以存在不确定时间并且可以随意锁定/解锁的线程安全上下文中调用此函数时,重要的是要注意此API不是线程安全的,必须在持有GIL的情况下执行。

返回值

如果格式说明符无效或命令名称不属于已知命令,则命令返回REDISMODULE_ERR

RedisModule_ReplicateVerbatim

int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

此函数将完全按照客户端调用的方式复制命令。请注意,复制的命令总是被包装在包含所有在给定模块命令执行中复制的命令的MULTI/EXEC中,按照它们被执行的顺序。

基本上,这种复制形式在你想要将命令完全按照其被调用的方式传播到从服务器和AOF文件时非常有用,因为可以重新执行该命令以确定性地从旧状态重新创建新状态。

需要注意的是,此API不是线程安全的,必须在持有GIL的情况下执行。

该函数总是返回 REDISMODULE_OK

数据库和关键API – 通用API

RedisModule_GetClientId

unsigned long long RedisModule_GetClientId(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

返回当前客户端调用当前活动模块命令的ID。返回的ID有以下几点保证:

  1. 每个不同的客户端ID都是不同的,因此如果同一个客户端多次执行模块命令,它可以被识别为具有相同的ID,否则ID将会不同。
  2. ID 单调递增。保证后来连接到服务器的客户端获得的 ID 大于之前看到的任何过去的 ID。

有效的ID范围是从1到2^64 - 1。如果返回0,意味着在当前函数调用的上下文中无法获取ID。

获取ID后,可以使用此宏检查命令执行是否确实在AOF加载的上下文中进行:

 if (RedisModule_IsAOFClient(RedisModule_GetClientId(ctx)) {
     // Handle it differently.
 }

RedisModule_GetClientUserNameById

RedisModuleString *RedisModule_GetClientUserNameById(RedisModuleCtx *ctx,
                                                     uint64_t id);

自版本起可用: 6.2.1

返回具有指定客户端ID的客户端使用的ACL用户名。 客户端ID可以通过RedisModule_GetClientId() API获取。如果客户端不存在,则返回NULL并将errno设置为ENOENT。如果客户端未使用ACL用户,则返回NULL并将errno设置为ENOTSUP。

RedisModule_GetClientInfoById

int RedisModule_GetClientInfoById(void *ci, uint64_t id);

自版本起可用: 6.0.0

返回有关指定ID的客户端的信息(该ID之前通过RedisModule_GetClientId() API获取)。如果客户端存在,则返回REDISMODULE_OK,否则返回REDISMODULE_ERR

当客户端存在且ci指针不为NULL,但指向一个类型为RedisModuleClientInfoV1的结构体时,该结构体之前已使用正确的REDISMODULE_CLIENTINFO_INITIALIZER_V1初始化,结构体将填充以下字段:

 uint64_t flags;         // REDISMODULE_CLIENTINFO_FLAG_*
 uint64_t id;            // Client ID
 char addr[46];          // IPv4 or IPv6 address.
 uint16_t port;          // TCP port.
 uint16_t db;            // Selected DB.

注意:在此调用的上下文中,客户端ID是无用的,因为我们已经知道,然而相同的结构可以在我们不知道客户端ID的其他上下文中使用,但返回的结构是相同的。

标志具有以下含义:

REDISMODULE_CLIENTINFO_FLAG_SSL          Client using SSL connection.
REDISMODULE_CLIENTINFO_FLAG_PUBSUB       Client in Pub/Sub mode.
REDISMODULE_CLIENTINFO_FLAG_BLOCKED      Client blocked in command.
REDISMODULE_CLIENTINFO_FLAG_TRACKING     Client with keys tracking on.
REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET   Client using unix domain socket.
REDISMODULE_CLIENTINFO_FLAG_MULTI        Client in MULTI state.

然而,传递NULL是一种仅检查客户端是否存在的方式,以防我们对任何额外信息不感兴趣。

这是当我们希望返回客户端信息结构时的正确用法:

 RedisModuleClientInfo ci = REDISMODULE_CLIENTINFO_INITIALIZER;
 int retval = RedisModule_GetClientInfoById(&ci,client_id);
 if (retval == REDISMODULE_OK) {
     printf("Address: %s\n", ci.addr);
 }

RedisModule_GetClientNameById

RedisModuleString *RedisModule_GetClientNameById(RedisModuleCtx *ctx,
                                                 uint64_t id);

自版本起可用: 7.0.3

返回具有给定ID的客户端连接的名称。

如果客户端ID不存在或客户端没有与之关联的名称,则返回NULL。

RedisModule_SetClientNameById

int RedisModule_SetClientNameById(uint64_t id, RedisModuleString *name);

自版本起可用: 7.0.3

设置具有给定ID的客户端的名称。这相当于客户端调用 CLIENT SETNAME name

成功时返回 REDISMODULE_OK。失败时返回 REDISMODULE_ERR,并且 errno 设置如下:

  • 如果客户端不存在,则返回ENOENT
  • EINVAL 如果名称包含无效字符

RedisModule_PublishMessage

int RedisModule_PublishMessage(RedisModuleCtx *ctx,
                               RedisModuleString *channel,
                               RedisModuleString *message);

自版本起可用: 6.0.0

向订阅者发布消息(参见PUBLISH命令)。

RedisModule_PublishMessageShard

int RedisModule_PublishMessageShard(RedisModuleCtx *ctx,
                                    RedisModuleString *channel,
                                    RedisModuleString *message);

自版本起可用: 7.0.0

向分片订阅者发布消息(参见SPUBLISH命令)。

RedisModule_GetSelectedDb

int RedisModule_GetSelectedDb(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

返回当前选择的数据库。

RedisModule_GetContextFlags

int RedisModule_GetContextFlags(RedisModuleCtx *ctx);

自版本起可用: 4.0.3

返回当前上下文的标志。这些标志提供了关于当前请求上下文的信息(客户端是Lua脚本还是在MULTI中),以及关于Redis实例的一般信息,即复制和持久性。

即使使用NULL上下文也可以调用此函数,但在这种情况下,以下标志将不会被报告:

  • LUA, MULTI, REPLICATED, DIRTY(更多信息见下文)。

可用的标志及其含义:

  • REDISMODULE_CTX_FLAGS_LUA: 命令正在Lua脚本中运行

  • REDISMODULE_CTX_FLAGS_MULTI: 命令正在事务内部运行

  • REDISMODULE_CTX_FLAGS_REPLICATED: 该命令是由主服务器通过复制链路发送的

  • REDISMODULE_CTX_FLAGS_MASTER: Redis实例是主节点

  • REDISMODULE_CTX_FLAGS_SLAVE: Redis实例是一个从节点

  • REDISMODULE_CTX_FLAGS_READONLY: Redis实例是只读的

  • REDISMODULE_CTX_FLAGS_CLUSTER: Redis实例处于集群模式

  • REDISMODULE_CTX_FLAGS_AOF: Redis实例已启用AOF

  • REDISMODULE_CTX_FLAGS_RDB: 实例已启用RDB

  • REDISMODULE_CTX_FLAGS_MAXMEMORY: 实例已设置最大内存

  • REDISMODULE_CTX_FLAGS_EVICT: 设置了最大内存并且有一个可能删除键的驱逐策略

  • REDISMODULE_CTX_FLAGS_OOM: 根据maxmemory设置,Redis内存不足。

  • REDISMODULE_CTX_FLAGS_OOM_WARNING: 在达到最大内存限制之前,剩余内存不足25%。

  • REDISMODULE_CTX_FLAGS_LOADING: 服务器正在加载RDB/AOF

  • REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE: 与主节点没有活动链接。

  • REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING: 副本正在尝试与主服务器连接。

  • REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING: 主节点 -> 从节点的RDB传输正在进行中。

  • REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE: 副本与其主服务器有一个活跃的连接。这与STALE状态相反。

  • REDISMODULE_CTX_FLAGS_ACTIVE_CHILD: 当前有一些后台进程在运行(RDB、AUX 或模块)。

  • REDISMODULE_CTX_FLAGS_MULTI_DIRTY: 由于脏的CAS(被修改的键),下一个EXEC将失败。

  • REDISMODULE_CTX_FLAGS_IS_CHILD: Redis 当前正在后台子进程中运行。

  • REDISMODULE_CTX_FLAGS_RESP3: 表示连接到该上下文的客户端正在使用RESP3。

  • REDISMODULE_CTX_FLAGS_SERVER_STARTUP: Redis实例正在启动

RedisModule_AvoidReplicaTraffic

int RedisModule_AvoidReplicaTraffic(void);

自版本起可用: 6.0.0

如果客户端向服务器发送了CLIENT PAUSE命令,或者Redis集群执行了手动故障转移,暂停客户端,则返回true。 当我们有一个带有副本的主节点,并且希望写入而不向复制通道添加更多数据时,这是必要的,以确保副本的复制偏移量与主节点的偏移量匹配。当这种情况发生时,可以安全地进行主节点的故障转移而不会丢失数据。

然而,模块可能会通过在命令执行之外的上下文中调用带有“!”标志的RedisModule_Call(),或者调用RedisModule_Replicate()来生成流量,例如在超时回调、线程安全上下文等情况下。当模块生成过多流量时,主节点和副本节点的偏移量将难以匹配,因为复制通道中有更多的数据需要发送。

因此,当此函数返回true时,模块可能希望尝试避免非常繁重的后台工作,这些工作会产生数据到复制通道的效果。这对于具有后台垃圾收集任务的模块,或者在定时器回调或其他周期性回调中定期执行写入并复制这些写入的模块非常有用。

RedisModule_SelectDb

int RedisModule_SelectDb(RedisModuleCtx *ctx, int newid);

自版本起可用: 4.0.0

更改当前选择的数据库。如果ID超出范围,则返回错误。

请注意,即使在模块调用此函数实现的Redis命令返回后,客户端仍将保留当前选择的数据库。

如果模块命令希望在不同的数据库中更改某些内容并返回到原始数据库,它应该在返回之前调用RedisModule_GetSelectedDb()以恢复旧的数据库编号。

RedisModule_KeyExists

int RedisModule_KeyExists(RedisModuleCtx *ctx, robj *keyname);

自版本起可用: 7.0.0

检查键是否存在,而不影响其最后访问时间。

这相当于使用模式 REDISMODULE_READ | REDISMODULE_OPEN_KEY_NOTOUCH 调用 RedisModule_OpenKey,然后检查是否返回了 NULL,如果没有,则在打开的键上调用 RedisModule_CloseKey

RedisModule_OpenKey

RedisModuleKey *RedisModule_OpenKey(RedisModuleCtx *ctx,
                                    robj *keyname,
                                    int mode);

自版本起可用: 4.0.0

返回一个表示Redis键的句柄,以便可以使用该键句柄作为参数调用其他API来对该键执行操作。

返回值是表示键的句柄,必须使用RedisModule_CloseKey()关闭。

如果键不存在并且请求了REDISMODULE_WRITE模式,仍然会返回句柄,因为可以对尚不存在的键执行操作(例如,在列表推送操作后创建)。如果模式仅为REDISMODULE_READ且键不存在,则返回NULL。然而,在NULL值上调用RedisModule_CloseKey()RedisModule_KeyType()仍然是安全的。

可以在模式参数下传递给API的额外标志:

  • REDISMODULE_OPEN_KEY_NOTOUCH - 打开键时避免触碰其LRU/LFU。
  • REDISMODULE_OPEN_KEY_NONOTIFY - 在键未命中时不触发键空间事件。
  • REDISMODULE_OPEN_KEY_NOSTATS - 不更新键空间命中/未命中计数器。
  • REDISMODULE_OPEN_KEY_NOEXPIRE - 避免删除惰性过期的键。
  • REDISMODULE_OPEN_KEY_NOEFFECTS - 避免获取键时产生任何影响。

RedisModule_GetOpenKeyModesAll

int RedisModule_GetOpenKeyModesAll(void);

自版本起可用: 7.2.0

返回完整的OpenKey模式掩码,使用返回值模块可以检查当前使用的redis服务器版本是否支持某些OpenKey模式。 示例:

   int supportedMode = RedisModule_GetOpenKeyModesAll();
   if (supportedMode & REDISMODULE_OPEN_KEY_NOTOUCH) {
         // REDISMODULE_OPEN_KEY_NOTOUCH is supported
   } else{
         // REDISMODULE_OPEN_KEY_NOTOUCH is not supported
   }

RedisModule_CloseKey

void RedisModule_CloseKey(RedisModuleKey *key);

自版本起可用: 4.0.0

关闭一个键句柄。

RedisModule_KeyType

int RedisModule_KeyType(RedisModuleKey *key);

自版本起可用: 4.0.0

返回键的类型。如果键指针为NULL,则返回REDISMODULE_KEYTYPE_EMPTY

RedisModule_ValueLength

size_t RedisModule_ValueLength(RedisModuleKey *key);

自版本起可用: 4.0.0

返回与键关联的值的长度。 对于字符串,这是字符串的长度。对于所有其他类型, 这是元素的数量(对于哈希,只计算键的数量)。

如果键指针为NULL或键为空,则返回零。

RedisModule_DeleteKey

int RedisModule_DeleteKey(RedisModuleKey *key);

自版本起可用: 4.0.0

如果键是开放写入的,移除它,并将键设置为接受新写入的空键(将按需创建)。成功时返回REDISMODULE_OK。如果键未开放写入,则返回REDISMODULE_ERR

RedisModule_UnlinkKey

int RedisModule_UnlinkKey(RedisModuleKey *key);

自版本起可用: 4.0.7

如果键是开放写入的,取消链接它(即以非阻塞方式删除它,不立即回收内存)并将键设置为接受新写入的空键(将按需创建)。 成功时返回REDISMODULE_OK。如果键未开放写入,则返回REDISMODULE_ERR

RedisModule_GetExpire

mstime_t RedisModule_GetExpire(RedisModuleKey *key);

自版本起可用: 4.0.0

返回键的过期值,以剩余的TTL毫秒数表示。 如果没有与键关联的TTL或键为空, 则返回REDISMODULE_NO_EXPIRE

RedisModule_SetExpire

int RedisModule_SetExpire(RedisModuleKey *key, mstime_t expire);

自版本起可用: 4.0.0

为键设置新的过期时间。如果设置了特殊的过期时间 REDISMODULE_NO_EXPIRE,则取消已有的过期时间(与PERSIST命令相同)。

请注意,expire 必须作为一个正整数提供,表示键应具有的 TTL 毫秒数。

函数成功时返回REDISMODULE_OK,如果键未打开写入或为空键,则返回REDISMODULE_ERR

RedisModule_GetAbsExpire

mstime_t RedisModule_GetAbsExpire(RedisModuleKey *key);

自以下版本可用: 6.2.2

返回键的过期值,作为绝对的Unix时间戳。 如果没有与键关联的TTL或者键为空, 则返回REDISMODULE_NO_EXPIRE

RedisModule_SetAbsExpire

int RedisModule_SetAbsExpire(RedisModuleKey *key, mstime_t expire);

自版本起可用: 6.2.2

为键设置新的过期时间。如果设置了特殊的过期时间 REDISMODULE_NO_EXPIRE,则取消已有的过期时间(与PERSIST命令相同)。

请注意,expire 必须作为一个正整数提供,表示键应具有的绝对 Unix 时间戳。

函数成功时返回REDISMODULE_OK,如果键未打开写入或为空键,则返回REDISMODULE_ERR

RedisModule_ResetDataset

void RedisModule_ResetDataset(int restart_aof, int async);

自版本起可用: 6.0.0

执行类似于FLUSHALL的操作,并可选地启动一个新的AOF文件(如果启用) 如果restart_aof为真,你必须确保触发此调用的命令不会传播到AOF文件中。 当async设置为true时,数据库内容将由后台线程释放。

RedisModule_DbSize

unsigned long long RedisModule_DbSize(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

返回当前数据库中的键的数量。

RedisModule_RandomKey

RedisModuleString *RedisModule_RandomKey(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

返回一个随机键的名称,如果当前数据库为空则返回NULL。

RedisModule_GetKeyNameFromOptCtx

const RedisModuleString *RedisModule_GetKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的键的名称。

RedisModule_GetToKeyNameFromOptCtx

const RedisModuleString *RedisModule_GetToKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的目标键的名称。

RedisModule_GetDbIdFromOptCtx

int RedisModule_GetDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的数据库ID。

RedisModule_GetToDbIdFromOptCtx

int RedisModule_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的目标数据库ID。

字符串类型的关键API

另请参阅RedisModule_ValueLength(),它返回字符串的长度。

RedisModule_StringSet

int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str);

自版本起可用: 4.0.0

如果键是开放写入的,将指定的字符串 'str' 设置为键的值,删除任何旧值。 成功时返回 REDISMODULE_OK。如果键未开放写入或存在活动迭代器,则返回 REDISMODULE_ERR

RedisModule_StringDMA

char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode);

自版本起可用: 4.0.0

准备与DMA访问相关的键值字符串,并返回一个指针和大小(通过引用),用户可以使用这些来直接通过指针读取或修改字符串。

'mode' 由以下标志的按位或运算组成:

REDISMODULE_READ -- Read access
REDISMODULE_WRITE -- Write access

如果DMA未被请求进行写入,返回的指针应仅以只读方式访问。

出错时(类型错误)返回NULL。

DMA访问规则:

  1. 从获取指针的那一刻起,不应调用其他关键写入函数,因为在整个过程中我们希望使用DMA访问来读取或修改字符串。

  2. 每次调用RedisModule_StringTruncate()后,要继续进行DMA访问,应再次调用RedisModule_StringDMA()以重新获取新的指针和长度。

  3. 如果返回的指针不是NULL,但长度为零,则不能触及任何字节(字符串为空,或者键本身为空),因此如果要扩大字符串,应使用RedisModule_StringTruncate()调用,然后再次调用StringDMA()以获取指针。

RedisModule_StringTruncate

int RedisModule_StringTruncate(RedisModuleKey *key, size_t newlen);

自版本起可用: 4.0.0

如果键是开放的用于写入并且是字符串类型,调整其大小,如果新长度大于旧长度,则用零字节填充。

在此调用之后,必须再次调用RedisModule_StringDMA()以继续使用新指针进行DMA访问。

函数成功时返回REDISMODULE_OK,错误时返回REDISMODULE_ERR,即键未打开写入,不是字符串或请求调整大小超过512 MB。

如果键为空,将使用新的字符串值创建一个字符串键,除非请求的新长度值为零。

列表类型的关键API

许多列表函数通过索引访问元素。由于列表本质上是一个双向链表,通过索引访问元素通常是一个O(N)操作。然而,如果元素是按顺序访问或索引接近,函数会优化为从前一个索引开始查找,而不是从列表的两端开始查找。

这使得可以使用简单的for循环高效地进行迭代:

long n = RedisModule_ValueLength(key);
for (long i = 0; i < n; i++) {
    RedisModuleString *elem = RedisModule_ListGet(key, i);
    // Do stuff...
}

请注意,在使用RedisModule_ListPopRedisModule_ListSetRedisModule_ListInsert修改列表后,内部迭代器将失效,因此下一个操作将需要线性查找。

以任何其他方式修改列表,例如使用RedisModule_Call(),当键打开时,会混淆内部迭代器,如果在进行此类修改后使用键,可能会导致问题。在这种情况下,必须重新打开键。

另请参阅RedisModule_ValueLength(),它返回列表的长度。

RedisModule_ListPush

int RedisModule_ListPush(RedisModuleKey *key,
                         int where,
                         RedisModuleString *ele);

自版本起可用: 4.0.0

将一个元素推入列表中,根据'where'参数决定是推入头部还是尾部 (REDISMODULE_LIST_HEADREDISMODULE_LIST_TAIL)。如果键指向一个为写入而打开的空键,则会创建该键。成功时,返回REDISMODULE_OK。失败时,返回REDISMODULE_ERR并设置errno如下:

  • 如果 key 或 ele 为 NULL,则返回 EINVAL。
  • 如果键的类型不是列表,则返回ENOTSUP。
  • 如果键未打开以进行写入,则返回 EBADF。

注意:在 Redis 7.0 之前,errno 未由此函数设置。

RedisModule_ListPop

RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where);

自版本起可用: 4.0.0

从列表中弹出一个元素,并将其作为模块字符串对象返回,用户应使用RedisModule_FreeString()或启用自动内存管理来释放它。where参数指定元素应从列表的开头还是结尾弹出(REDISMODULE_LIST_HEADREDISMODULE_LIST_TAIL)。如果失败,命令返回NULL并设置errno如下:

  • 如果 key 为 NULL,则返回 EINVAL。
  • 如果键为空或类型不是列表,则返回ENOTSUP。
  • 如果键未打开以供写入,则返回EBADF。

注意:在Redis 7.0之前,errno未由此函数设置。

RedisModule_ListGet

RedisModuleString *RedisModule_ListGet(RedisModuleKey *key, long index);

自版本起可用: 7.0.0

返回存储在key中的列表中索引index处的元素,类似于LINDEX命令。该元素应使用RedisModule_FreeString()或自动内存管理来释放。

索引是从零开始的,所以0表示第一个元素,1表示第二个元素,依此类推。负索引可以用来指定从列表尾部开始的元素。在这里,-1表示最后一个元素,-2表示倒数第二个元素,依此类推。

当在给定的键和索引处找不到值时,返回NULL,并且errno设置如下:

  • 如果 key 为 NULL,则返回 EINVAL。
  • 如果键不是列表,则返回ENOTSUP。
  • EBADF 如果密钥未打开以供读取。
  • 如果索引不是列表中的有效索引,则返回EDOM。

RedisModule_ListSet

int RedisModule_ListSet(RedisModuleKey *key,
                        long index,
                        RedisModuleString *value);

自版本起可用: 7.0.0

替换存储在key中的列表中索引index处的元素。

索引是从零开始的,所以0表示第一个元素,1表示第二个元素,依此类推。负索引可以用来指定从列表尾部开始的元素。这里,-1表示最后一个元素,-2表示倒数第二个元素,依此类推。

成功时,返回REDISMODULE_OK。失败时,返回REDISMODULE_ERR,并且errno设置如下:

  • 如果 key 或 value 为 NULL,则返回 EINVAL。
  • 如果键不是列表,则返回ENOTSUP。
  • 如果键未打开以供写入,则返回EBADF。
  • 如果索引不是列表中的有效索引,则返回 EDOM。

RedisModule_ListInsert

int RedisModule_ListInsert(RedisModuleKey *key,
                           long index,
                           RedisModuleString *value);

自版本起可用: 7.0.0

在给定索引处插入一个元素。

索引是从零开始的,所以0表示第一个元素,1表示第二个元素,依此类推。负索引可以用来指定从列表尾部开始的元素。这里,-1表示最后一个元素,-2表示倒数第二个,依此类推。索引是插入元素后的元素索引。

成功时,返回REDISMODULE_OK。失败时,返回REDISMODULE_ERR,并设置errno如下:

  • 如果 key 或 value 为 NULL,则返回 EINVAL。
  • 如果键的类型不是列表,则返回ENOTSUP。
  • 如果键未打开以供写入,则返回EBADF。
  • 如果索引不是列表中的有效索引,则返回EDOM。

RedisModule_ListDelete

int RedisModule_ListDelete(RedisModuleKey *key, long index);

自版本起可用: 7.0.0

移除给定索引处的元素。索引从0开始。也可以使用负索引,从列表末尾开始计数。

成功时,返回REDISMODULE_OK。失败时,返回REDISMODULE_ERR,并且errno设置如下:

  • 如果 key 或 value 为 NULL,则返回 EINVAL。
  • 如果键不是列表,则返回ENOTSUP。
  • 如果键未打开以供写入,则返回EBADF。
  • 如果索引不是列表中的有效索引,则返回 EDOM。

Sorted Set 类型的关键 API

另请参阅RedisModule_ValueLength(),它返回一个有序集合的长度。

RedisModule_ZsetAdd

int RedisModule_ZsetAdd(RedisModuleKey *key,
                        double score,
                        RedisModuleString *ele,
                        int *flagsptr);

自版本起可用: 4.0.0

向已排序的集合中添加一个新元素,并指定'score'。 如果元素已经存在,则更新其分数。

如果键是一个空的开放键设置用于写入,则在值处创建一个新的排序集。

可以通过指针将额外的标志传递给函数,这些标志既用于接收输入,也用于在函数返回时通信状态。如果没有使用特殊标志,'flagsptr'可以为NULL。

输入标志为:

REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score. 
                     Do nothing otherwise. Can optionally be combined with XX.
REDISMODULE_ZADD_LT: If element exists, new score must be less than the current score.
                     Do nothing otherwise. Can optionally be combined with XX.

输出标志为:

REDISMODULE_ZADD_ADDED: The new element was added to the sorted set.
REDISMODULE_ZADD_UPDATED: The score of the element was updated.
REDISMODULE_ZADD_NOP: No operation was performed because XX or NX flags.

成功时,函数返回 REDISMODULE_OK。在以下错误情况下,返回 REDISMODULE_ERR

  • 密钥未打开以进行写入。
  • 键的类型错误。
  • 'score' 双精度值不是数字(NaN)。

RedisModule_ZsetIncrby

int RedisModule_ZsetIncrby(RedisModuleKey *key,
                           double score,
                           RedisModuleString *ele,
                           int *flagsptr,
                           double *newscore);

自版本起可用: 4.0.0

此函数的工作方式与RedisModule_ZsetAdd()完全相同,但不是设置新分数,而是增加现有元素的分数,或者如果元素尚不存在,则假设旧分数为零并添加该元素。

输入和输出标志以及返回值具有完全相同的含义,唯一的区别是,即使'score'是一个有效的双精度数,但将其添加到现有分数中会导致NaN(非数字)条件时,此函数将返回REDISMODULE_ERR

此函数有一个额外的字段 'newscore',如果不为 NULL,则在增量后填充元素的新分数,如果没有错误返回。

RedisModule_ZsetRem

int RedisModule_ZsetRem(RedisModuleKey *key,
                        RedisModuleString *ele,
                        int *deleted);

自版本起可用: 4.0.0

从排序集合中移除指定的元素。 该函数在成功时返回REDISMODULE_OK,在以下任一条件下返回REDISMODULE_ERR

  • 密钥未打开以进行写入。
  • 键的类型错误。

返回值并不表示元素是否真的被移除(因为它存在与否),而只是表示函数是否成功执行。

为了知道元素是否被移除,必须传递额外的参数 'deleted',该参数通过引用填充整数,根据操作结果将其设置为1或0。如果调用者不关心元素是否真的被移除,'deleted' 参数可以为 NULL。

空键将被正确处理,不做任何操作。

RedisModule_ZsetScore

int RedisModule_ZsetScore(RedisModuleKey *key,
                          RedisModuleString *ele,
                          double *score);

自版本起可用: 4.0.0

成功时,检索与排序集合元素'ele'关联的双精度分数并返回REDISMODULE_OK。否则返回REDISMODULE_ERR以表示以下条件之一:

  • 在排序集合中没有这样的元素 'ele'。
  • 键不是一个有序集合。
  • 键是一个开放的空白键。

Sorted Set 迭代器的关键 API

RedisModule_ZsetRangeStop

void RedisModule_ZsetRangeStop(RedisModuleKey *key);

自版本起可用: 4.0.0

停止一个有序集合的迭代。

RedisModule_ZsetRangeEndReached

int RedisModule_ZsetRangeEndReached(RedisModuleKey *key);

自版本起可用: 4.0.0

返回“范围结束”标志值以表示迭代的结束。

RedisModule_ZsetFirstInScoreRange

int RedisModule_ZsetFirstInScoreRange(RedisModuleKey *key,
                                      double min,
                                      double max,
                                      int minex,
                                      int maxex);

自版本起可用: 4.0.0

设置一个排序集合迭代器,寻找指定范围内的第一个元素。如果迭代器正确初始化,则返回REDISMODULE_OK,否则在以下情况下返回REDISMODULE_ERR

  1. 存储在键中的值不是有序集合,或者键为空。

范围是根据两个双精度值'min'和'max'指定的。两者都可以使用以下两个宏来设置为无限:

  • REDISMODULE_POSITIVE_INFINITE 表示正无穷大值
  • REDISMODULE_NEGATIVE_INFINITE 表示负无穷大值

'minex' 和 'maxex' 参数,如果为真,则分别设置一个范围,其中最小值和最大值是排他的(不包括在内),而不是包含的。

RedisModule_ZsetLastInScoreRange

int RedisModule_ZsetLastInScoreRange(RedisModuleKey *key,
                                     double min,
                                     double max,
                                     int minex,
                                     int maxex);

自版本起可用: 4.0.0

RedisModule_ZsetFirstInScoreRange()完全相同,但迭代的起始点选择的是范围内的最后一个元素。

RedisModule_ZsetFirstInLexRange

int RedisModule_ZsetFirstInLexRange(RedisModuleKey *key,
                                    RedisModuleString *min,
                                    RedisModuleString *max);

自版本起可用: 4.0.0

设置一个排序集合迭代器,寻找指定字典范围内的第一个元素。如果迭代器正确初始化,则返回REDISMODULE_OK,否则在以下情况下返回REDISMODULE_ERR

  1. 存储在键中的值不是有序集合,或者键为空。
  2. 字典范围'min'和'max'格式无效。

'min' 和 'max' 应该作为两个 RedisModuleString 对象提供, 格式与传递给 ZRANGEBYLEX 命令的参数相同。 该函数不会获取对象的所有权,因此可以在迭代器设置后尽快释放它们。

RedisModule_ZsetLastInLexRange

int RedisModule_ZsetLastInLexRange(RedisModuleKey *key,
                                   RedisModuleString *min,
                                   RedisModuleString *max);

自版本起可用: 4.0.0

RedisModule_ZsetFirstInLexRange()完全相同,但选择范围的最后一个元素作为迭代的起点。

RedisModule_ZsetRangeCurrentElement

RedisModuleString *RedisModule_ZsetRangeCurrentElement(RedisModuleKey *key,
                                                       double *score);

自版本起可用: 4.0.0

返回当前活动的排序集合迭代器的排序集合元素,如果迭代器中指定的范围不包含任何元素,则返回NULL。

RedisModule_ZsetRangeNext

int RedisModule_ZsetRangeNext(RedisModuleKey *key);

自版本起可用: 4.0.0

转到排序集合迭代器的下一个元素。如果有下一个元素,则返回1;如果已经在最新元素或范围内不包含任何项目,则返回0。

RedisModule_ZsetRangePrev

int RedisModule_ZsetRangePrev(RedisModuleKey *key);

自版本起可用: 4.0.0

转到排序集合迭代器的前一个元素。如果有前一个元素,则返回1;如果已经在第一个元素或范围内不包含任何项目,则返回0。

哈希类型的关键API

另请参阅RedisModule_ValueLength(),它返回哈希中的字段数量。

RedisModule_HashSet

int RedisModule_HashSet(RedisModuleKey *key, int flags, ...);

自版本起可用: 4.0.0

将指定哈希字段的字段设置为指定值。 如果键是一个可写入的空键,则会创建一个空的哈希值,以便设置指定的字段。

该函数是可变参数的,用户必须指定字段名称和值的对,两者都作为RedisModuleString指针(除非设置了CFIELD选项,稍后见)。在字段/值指针对的末尾,必须指定NULL作为最后一个参数,以表示可变参数函数中参数的结束。

示例将哈希 argv[1] 设置为值 argv[2]:

 RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],argv[2],NULL);

该函数还可以用于删除字段(如果存在),通过将它们设置为REDISMODULE_HASH_DELETE的指定值:

 RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],
                     REDISMODULE_HASH_DELETE,NULL);

命令的行为会随着指定的标志而变化,如果不需要特殊行为,可以设置为REDISMODULE_HASH_NONE

REDISMODULE_HASH_NX: The operation is performed only if the field was not
                     already existing in the hash.
REDISMODULE_HASH_XX: The operation is performed only if the field was
                     already existing, so that a new value could be
                     associated to an existing filed, but no new fields
                     are created.
REDISMODULE_HASH_CFIELDS: The field names passed are null terminated C
                          strings instead of RedisModuleString objects.
REDISMODULE_HASH_COUNT_ALL: Include the number of inserted fields in the
                            returned number, in addition to the number of
                            updated and deleted fields. (Added in Redis
                            6.2.)

除非指定了NX,否则命令会用新值覆盖旧字段值。

当使用REDISMODULE_HASH_CFIELDS时,字段名称使用普通的C字符串报告,因此例如要删除字段"foo",可以使用以下代码:

 RedisModule_HashSet(key,REDISMODULE_HASH_CFIELDS,"foo",
                     REDISMODULE_HASH_DELETE,NULL);

返回值:

在调用之前存在于哈希中的字段数量,这些字段已被更新(其旧值已被新值替换)或删除。如果设置了标志REDISMODULE_HASH_COUNT_ALL,则之前不存在于哈希中的插入字段也会被计数。

如果返回值为零,errno 将设置如下(自 Redis 6.2 起):

  • 如果设置了任何未知标志或key为NULL,则返回EINVAL。
  • 如果键与非哈希值相关联,则返回ENOTSUP。
  • EBADF 如果密钥未以写入模式打开。
  • 如果没有字段被计数,如上述返回值部分所述,则返回ENOENT。 这实际上不是一个错误。如果所有字段都是刚刚创建的并且COUNT_ALL标志未设置,或者由于NX和XX标志而阻止了更改,则返回值可能为零。

注意:此函数的返回值语义在Redis 6.2和旧版本之间有很大不同。使用它的模块应确定Redis版本并相应地处理。

RedisModule_HashGet

int RedisModule_HashGet(RedisModuleKey *key, int flags, ...);

自版本起可用: 4.0.0

从哈希值中获取字段。此函数使用可变数量的参数调用,交替使用字段名称(作为RedisModuleString指针)和指向RedisModuleString指针的指针,如果字段存在,则设置为字段的值,如果字段不存在,则设置为NULL。在字段/值指针对的末尾,必须指定NULL作为最后一个参数,以表示可变参数函数中参数的结束。

这是一个使用示例:

 RedisModuleString *first, *second;
 RedisModule_HashGet(mykey,REDISMODULE_HASH_NONE,argv[1],&first,
                     argv[2],&second,NULL);

RedisModule_HashSet()一样,可以通过传递不同于REDISMODULE_HASH_NONE的标志来指定命令的行为:

REDISMODULE_HASH_CFIELDS: 字段名称为以空字符结尾的C字符串。

REDISMODULE_HASH_EXISTS: 不是设置字段的值,而是报告字段是否存在,并期望每个对的第二个元素是一个整数指针。

REDISMODULE_HASH_CFIELDS 的示例:

 RedisModuleString *username, *hashedpass;
 RedisModule_HashGet(mykey,REDISMODULE_HASH_CFIELDS,"username",&username,"hp",&hashedpass, NULL);

REDISMODULE_HASH_EXISTS的示例:

 int exists;
 RedisModule_HashGet(mykey,REDISMODULE_HASH_EXISTS,argv[1],&exists,NULL);

函数成功时返回REDISMODULE_OK,如果键不是哈希值则返回REDISMODULE_ERR

内存管理:

返回的RedisModuleString对象应使用 RedisModule_FreeString()释放,或通过启用自动内存管理来释放。

流类型的关键API

有关流的介绍,请参见 https://redis.io/topics/streams-intro

类型 RedisModuleStreamID,用于流函数,是一个包含两个64位字段的结构体,定义如下

typedef struct RedisModuleStreamID {
    uint64_t ms;
    uint64_t seq;
} RedisModuleStreamID;

另请参阅RedisModule_ValueLength(),它返回流的长度,以及转换函数RedisModule_StringToStreamID()RedisModule_CreateStringFromStreamID()

RedisModule_StreamAdd

int RedisModule_StreamAdd(RedisModuleKey *key,
                          int flags,
                          RedisModuleStreamID *id,
                          RedisModuleString **argv,
                          long numfields);

自版本起可用: 6.2.0

向流中添加一个条目。类似于XADD,但不进行修剪。

  • key: 流存储(或将存储)的键
  • flags: 一个位字段
    • REDISMODULE_STREAM_ADD_AUTOID: 自动分配一个流ID,类似于 * 在 XADD 命令中。
  • id: 如果设置了AUTOID标志,这里将返回分配的ID。如果设置了AUTOID并且你不关心接收ID,可以为NULL。如果未设置AUTOID,这是请求的ID。
  • argv: 一个指向大小为 numfields * 2 的数组的指针,包含字段和值。
  • numfields: argv 中字段-值对的数量。

如果条目已添加,则返回REDISMODULE_OK。失败时, 返回REDISMODULE_ERR,并设置errno如下:

  • EINVAL 如果使用无效参数调用
  • 如果键引用的值类型不是流,则返回ENOTSUP
  • EBADF 如果密钥未以写入方式打开
  • 如果给定的ID是0-0或不大于流中的所有其他ID(仅当AUTOID标志未设置时),则返回EDOM
  • 如果流已达到最后一个可能的ID,则为EFBIG
  • ERANGE 如果元素太大无法存储。

RedisModule_StreamDelete

int RedisModule_StreamDelete(RedisModuleKey *key, RedisModuleStreamID *id);

自版本起可用: 6.2.0

从流中删除一个条目。

  • key: 一个已打开用于写入的键,没有启动流迭代器。
  • id: 要删除的条目的流ID。

成功时返回REDISMODULE_OK。失败时返回REDISMODULE_ERR,并设置errno如下:

  • EINVAL 如果使用无效参数调用
  • 如果键引用的值类型不是流类型,或者键为空,则返回ENOTSUP
  • EBADF 如果键未打开以进行写入,或者如果流迭代器与键相关联
  • 如果不存在具有给定流ID的条目,则返回ENOENT

另请参阅RedisModule_StreamIteratorDelete(),用于在使用流迭代器迭代时删除当前条目。

RedisModule_StreamIteratorStart

int RedisModule_StreamIteratorStart(RedisModuleKey *key,
                                    int flags,
                                    RedisModuleStreamID *start,
                                    RedisModuleStreamID *end);

自版本起可用: 6.2.0

设置一个流迭代器。

  • key: 使用RedisModule_OpenKey()打开的用于读取的流键。
  • flags:
    • REDISMODULE_STREAM_ITERATOR_EXCLUSIVE: 不包括startend在迭代范围内。
    • REDISMODULE_STREAM_ITERATOR_REVERSE: 以相反的顺序迭代,从范围的end开始。
  • start: 范围的下限。使用 NULL 表示流的开始。
  • end: 范围的上限。使用 NULL 表示流的结束。

成功时返回REDISMODULE_OK。失败时返回REDISMODULE_ERR,并设置errno如下:

  • EINVAL 如果使用无效参数调用
  • 如果键引用的值类型不是流类型,或者键为空,则返回ENOTSUP
  • EBADF 如果键未打开以进行写入,或者如果流迭代器已经与该键关联
  • 如果 startend 超出有效范围,则返回 EDOM

成功时返回REDISMODULE_OK,如果键不引用流或提供了无效参数,则返回REDISMODULE_ERR

流ID通过RedisModule_StreamIteratorNextID()获取,并且对于每个流ID,字段和值通过RedisModule_StreamIteratorNextField()获取。迭代器通过调用RedisModule_StreamIteratorStop()释放。

示例(错误处理已省略):

RedisModule_StreamIteratorStart(key, 0, startid_ptr, endid_ptr);
RedisModuleStreamID id;
long numfields;
while (RedisModule_StreamIteratorNextID(key, &id, &numfields) ==
       REDISMODULE_OK) {
    RedisModuleString *field, *value;
    while (RedisModule_StreamIteratorNextField(key, &field, &value) ==
           REDISMODULE_OK) {
        //
        // ... Do stuff ...
        //
        RedisModule_FreeString(ctx, field);
        RedisModule_FreeString(ctx, value);
    }
}
RedisModule_StreamIteratorStop(key);

RedisModule_StreamIteratorStop

int RedisModule_StreamIteratorStop(RedisModuleKey *key);

自版本起可用: 6.2.0

停止使用RedisModule_StreamIteratorStart()创建的流迭代器并回收其内存。

成功时返回REDISMODULE_OK。失败时返回REDISMODULE_ERR,并设置errno如下:

  • 如果使用NULL键调用,则返回EINVAL
  • 如果键引用的值类型不是流类型,或者键为空,则返回ENOTSUP
  • EBADF 如果键未以写入方式打开,或者没有流迭代器与键关联

RedisModule_StreamIteratorNextID

int RedisModule_StreamIteratorNextID(RedisModuleKey *key,
                                     RedisModuleStreamID *id,
                                     long *numfields);

自版本起可用: 6.2.0

查找下一个流条目并返回其流ID和字段数量。

  • key: 使用RedisModule_StreamIteratorStart()启动流迭代器的键。
  • id: 返回的流ID。如果您不关心,则为NULL。
  • numfields: 找到的流条目中的字段数量。如果你不关心,则为NULL。

如果找到条目,则返回REDISMODULE_OK并设置*id*numfields。 失败时,返回REDISMODULE_ERR并设置errno如下:

  • 如果使用NULL键调用,则返回EINVAL
  • 如果键引用的值类型不是流类型,或者键为空,则返回ENOTSUP
  • EBADF 如果没有流迭代器与键相关联
  • 如果迭代器范围内没有更多条目,则返回ENOENT

在实践中,如果在成功调用RedisModule_StreamIteratorStart()之后,并且使用相同的键调用RedisModule_StreamIteratorNextID(),则可以安全地假设返回值为REDISMODULE_ERR意味着没有更多的条目。

使用 RedisModule_StreamIteratorNextField() 来检索字段和值。 请参阅 RedisModule_StreamIteratorStart() 的示例。

RedisModule_StreamIteratorNextField

int RedisModule_StreamIteratorNextField(RedisModuleKey *key,
                                        RedisModuleString **field_ptr,
                                        RedisModuleString **value_ptr);

自版本起可用: 6.2.0

检索当前流ID的下一个字段及其在流迭代中的对应值。在调用RedisModule_StreamIteratorNextID()后,应重复调用此函数以获取每个字段-值对。

  • key: 流迭代器已启动的键。
  • field_ptr: 这是返回字段的地方。
  • value_ptr: 这是返回值的地方。

返回REDISMODULE_OK并将*field_ptr*value_ptr指向新分配的RedisModuleString对象。如果启用了自动内存管理,回调完成后字符串对象会自动释放。失败时,返回REDISMODULE_ERR并设置errno如下:

  • 如果使用NULL键调用,则返回EINVAL
  • 如果键引用的值类型不是流类型,或者键为空,则返回ENOTSUP
  • EBADF 如果没有流迭代器与键相关联
  • 如果当前流条目中没有更多字段,则返回ENOENT

在实践中,如果在成功调用RedisModule_StreamIteratorNextID()之后,并且使用相同的键调用RedisModule_StreamIteratorNextField(),则可以安全地假设返回值为REDISMODULE_ERR意味着没有更多的字段。

请参见RedisModule_StreamIteratorStart()中的示例。

RedisModule_StreamIteratorDelete

int RedisModule_StreamIteratorDelete(RedisModuleKey *key);

自版本起可用: 6.2.0

在迭代时删除当前流条目。

此函数可以在调用RedisModule_StreamIteratorNextID()之后或调用RedisModule_StreamIteratorNextField()之后调用。

成功时返回REDISMODULE_OK。失败时返回REDISMODULE_ERR,并设置errno如下:

  • 如果 key 为 NULL,则返回 EINVAL
  • 如果键为空或类型不是流,则返回ENOTSUP
  • EBADF 如果键未打开以进行写入,或者尚未启动迭代器
  • 如果迭代器没有当前流条目,则返回ENOENT

RedisModule_StreamTrimByLength

long long RedisModule_StreamTrimByLength(RedisModuleKey *key,
                                         int flags,
                                         long long length);

自版本起可用: 6.2.0

按长度修剪流,类似于带有MAXLEN的XTRIM。

  • key: 用于写入的键。
  • flags: 一个位字段
    • REDISMODULE_STREAM_TRIM_APPROX: 如果可以提高性能,则减少修剪,例如使用 ~ 的 XTRIM。
  • length: 修剪后保留的流条目数量。

返回删除的条目数。如果失败,则返回负值,并且errno被设置为以下值:

  • EINVAL 如果使用无效参数调用
  • 如果键为空或类型不是流,则返回ENOTSUP
  • EBADF 如果密钥未打开以供写入

RedisModule_StreamTrimByID

long long RedisModule_StreamTrimByID(RedisModuleKey *key,
                                     int flags,
                                     RedisModuleStreamID *id);

自版本起可用: 6.2.0

通过ID修剪流,类似于使用MINID的XTRIM。

  • key: 用于写入的键。
  • flags: 一个位字段
    • REDISMODULE_STREAM_TRIM_APPROX: 如果可以提高性能,则减少修剪,例如使用 ~ 的 XTRIM。
  • id: 修剪后保留的最小流ID。

返回删除的条目数。如果失败,则返回负值,并设置errno如下:

  • EINVAL 如果使用无效参数调用
  • 如果键为空或类型不是流,则返回ENOTSUP
  • EBADF 如果密钥未打开以供写入

从模块调用Redis命令

RedisModule_Call() 向Redis发送命令。其余的函数处理回复。

RedisModule_FreeCallReply

void RedisModule_FreeCallReply(RedisModuleCallReply *reply);

自版本起可用: 4.0.0

释放一个调用回复及其包含的所有嵌套回复(如果它是一个数组)。

RedisModule_CallReplyType

int RedisModule_CallReplyType(RedisModuleCallReply *reply);

自版本起可用: 4.0.0

返回以下之一的回复类型:

  • REDISMODULE_REPLY_UNKNOWN
  • REDISMODULE_REPLY_STRING
  • REDISMODULE_REPLY_ERROR
  • REDISMODULE_REPLY_INTEGER
  • REDISMODULE_REPLY_ARRAY
  • REDISMODULE_REPLY_NULL
  • REDISMODULE_REPLY_MAP
  • REDISMODULE_REPLY_SET
  • REDISMODULE_REPLY_BOOL
  • REDISMODULE_REPLY_DOUBLE
  • REDISMODULE_REPLY_BIG_NUMBER
  • REDISMODULE_REPLY_VERBATIM_STRING
  • REDISMODULE_REPLY_ATTRIBUTE
  • REDISMODULE_REPLY_PROMISE

RedisModule_CallReplyLength

size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply);

自版本起可用: 4.0.0

返回适用的回复类型长度。

RedisModule_CallReplyArrayElement

RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply,
                                                        size_t idx);

自版本起可用: 4.0.0

返回数组回复的第'idx'个嵌套调用回复元素,如果回复类型错误或索引超出范围,则返回NULL。

RedisModule_CallReplyInteger

long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply);

自版本起可用: 4.0.0

返回整数回复的long long

RedisModule_CallReplyDouble

double RedisModule_CallReplyDouble(RedisModuleCallReply *reply);

自版本起可用: 7.0.0

返回双精度回复的双精度值。

RedisModule_CallReplyBigNumber

const char *RedisModule_CallReplyBigNumber(RedisModuleCallReply *reply,
                                           size_t *len);

自版本起可用: 7.0.0

返回一个大数回复的大数值。

RedisModule_CallReplyVerbatim

const char *RedisModule_CallReplyVerbatim(RedisModuleCallReply *reply,
                                          size_t *len,
                                          const char **format);

自版本起可用: 7.0.0

返回逐字字符串回复的值, 可以提供一个可选的输出参数以获取逐字回复格式。

RedisModule_CallReplyBool

int RedisModule_CallReplyBool(RedisModuleCallReply *reply);

自版本起可用: 7.0.0

返回布尔回复的布尔值。

RedisModule_CallReplySetElement

RedisModuleCallReply *RedisModule_CallReplySetElement(RedisModuleCallReply *reply,
                                                      size_t idx);

自版本起可用: 7.0.0

返回集合回复的第'idx'个嵌套调用回复元素,如果回复类型错误或索引超出范围,则返回NULL。

RedisModule_CallReplyMapElement

int RedisModule_CallReplyMapElement(RedisModuleCallReply *reply,
                                    size_t idx,
                                    RedisModuleCallReply **key,
                                    RedisModuleCallReply **val);

自版本起可用: 7.0.0

检索地图回复的第'idx'个键和值。

返回:

  • REDISMODULE_OK 成功时。
  • REDISMODULE_ERR 如果索引超出范围或回复类型错误。

keyvalue 参数用于通过引用返回,如果不需要,可以为 NULL。

RedisModule_CallReplyAttribute

RedisModuleCallReply *RedisModule_CallReplyAttribute(RedisModuleCallReply *reply);

自版本起可用: 7.0.0

返回给定回复的属性,如果属性不存在则返回NULL。

RedisModule_CallReplyAttributeElement

int RedisModule_CallReplyAttributeElement(RedisModuleCallReply *reply,
                                          size_t idx,
                                          RedisModuleCallReply **key,
                                          RedisModuleCallReply **val);

自版本起可用: 7.0.0

检索属性回复的第'idx'个键和值。

返回:

  • REDISMODULE_OK 成功时。
  • REDISMODULE_ERR 如果索引超出范围或回复类型错误。

keyvalue 参数用于通过引用返回,如果不需要,可以为 NULL。

RedisModule_CallReplyPromiseSetUnblockHandler

void RedisModule_CallReplyPromiseSetUnblockHandler(RedisModuleCallReply *reply,
                                                   RedisModuleOnUnblocked on_unblock,
                                                   void *private_data);

自版本起可用: 7.2.0

在给定的承诺 RedisModuleCallReply 上设置解除阻塞处理程序(回调和私有数据)。 给定的回复必须是承诺类型(REDISMODULE_REPLY_PROMISE)。

RedisModule_CallReplyPromiseAbort

int RedisModule_CallReplyPromiseAbort(RedisModuleCallReply *reply,
                                      void **private_data);

自版本起可用: 7.2.0

中止给定承诺 RedisModuleCallReply 的执行。 如果中止成功,则返回 REDMODULE_OK,如果无法中止执行(执行已完成),则返回 REDISMODULE_ERR。 如果执行被中止(返回了 REDMODULE_OK),则 private_data 输出参数将设置为在 'RedisModule_CallReplyPromiseSetUnblockHandler' 上给出的私有数据的值,以便调用者能够释放私有数据。

如果执行被成功中止,可以保证不会调用解除阻塞的处理程序。 也就是说,中止操作可能会成功,但操作仍可能继续。 例如,如果一个模块实现了某些阻塞命令并且不尊重断开连接的回调,这种情况就可能发生。对于纯Redis命令,这种情况不会发生。

RedisModule_CallReplyStringPtr

const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply,
                                           size_t *len);

自版本起可用: 4.0.0

返回字符串或错误回复的指针和长度。

RedisModule_CreateStringFromCallReply

RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply);

自版本起可用: 4.0.0

从类型为字符串、错误或整数的调用回复中返回一个新的字符串对象。否则(错误的回复类型)返回NULL。

RedisModule_SetContextUser

void RedisModule_SetContextUser(RedisModuleCtx *ctx,
                                const RedisModuleUser *user);

自版本起可用: 7.0.6

修改RedisModule_Call将使用的用户(例如用于ACL检查)

RedisModule_Call

RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx,
                                       const char *cmdname,
                                       const char *fmt,
                                       ...);

自版本起可用: 4.0.0

导出的API用于从模块调用任何Redis命令。

  • cmdname: 要调用的Redis命令。

  • fmt: A format specifier string for the command's arguments. Each of the arguments should be specified by a valid type specification. The format specifier can also contain the modifiers !, A, 3 and R which don't have a corresponding argument.

    • b -- The argument is a buffer and is immediately followed by another argument that is the buffer's length.

    • c -- The argument is a pointer to a plain C string (null-terminated).

    • l -- The argument is a long long integer.

    • s -- The argument is a RedisModuleString.

    • v -- The argument(s) is a vector of RedisModuleString.

    • ! -- Sends the Redis command and its arguments to replicas and AOF.

    • A -- Suppress AOF propagation, send only to replicas (requires !).

    • R -- Suppress replicas propagation, send only to AOF (requires !).

    • 3 -- Return a RESP3 reply. This will change the command reply. e.g., HGETALL returns a map instead of a flat array.

    • 0 -- Return the reply in auto mode, i.e. the reply format will be the same as the client attached to the given RedisModuleCtx. This will probably used when you want to pass the reply directly to the client.

    • C -- Run a command as the user attached to the context. User is either attached automatically via the client that directly issued the command and created the context or via RedisModule_SetContextUser. If the context is not directly created by an issued command (such as a background context and no user was set on it via RedisModule_SetContextUser, RedisModule_Call will fail. Checks if the command can be executed according to ACL rules and causes the command to run as the determined user, so that any future user dependent activity, such as ACL checks within scripts will proceed as expected. Otherwise, the command will run as the Redis unrestricted user.

    • S -- Run the command in a script mode, this means that it will raise an error if a command which are not allowed inside a script (flagged with the deny-script flag) is invoked (like SHUTDOWN). In addition, on script mode, write commands are not allowed if there are not enough good replicas (as configured with min-replicas-to-write) or when the server is unable to persist to the disk.

    • W -- Do not allow to run any write command (flagged with the write flag).

    • M -- Do not allow deny-oom flagged commands when over the memory limit.

    • E -- Return error as RedisModuleCallReply. If there is an error before invoking the command, the error is returned using errno mechanism. This flag allows to get the error also as an error CallReply with relevant error message.

    • 'D' -- A "Dry Run" mode. Return before executing the underlying call(). If everything succeeded, it will return with a NULL, otherwise it will return with a CallReply object denoting the error, as if it was called with the 'E' code.

    • 'K' -- Allow running blocking commands. If enabled and the command gets blocked, a special REDISMODULE_REPLY_PROMISE will be returned. This reply type indicates that the command was blocked and the reply will be given asynchronously. The module can use this reply object to set a handler which will be called when the command gets unblocked using RedisModule_CallReplyPromiseSetUnblockHandler. The handler must be set immediately after the command invocation (without releasing the Redis lock in between). If the handler is not set, the blocking command will still continue its execution but the reply will be ignored (fire and forget), notice that this is dangerous in case of role change, as explained below. The module can use RedisModule_CallReplyPromiseAbort to abort the command invocation if it was not yet finished (see RedisModule_CallReplyPromiseAbort documentation for more details). It is also the module's responsibility to abort the execution on role change, either by using server event (to get notified when the instance becomes a replica) or relying on the disconnect callback of the original client. Failing to do so can result in a write operation on a replica. Unlike other call replies, promise call reply must be freed while the Redis GIL is locked. Notice that on unblocking, the only promise is that the unblock handler will be called, If the blocking RedisModule_Call caused the module to also block some real client (using RedisModule_BlockClient), it is the module responsibility to unblock this client on the unblock handler. On the unblock handler it is only allowed to perform the following: * Calling additional Redis commands using RedisModule_Call * Open keys using RedisModule_OpenKey * Replicate data to the replica or AOF

         Specifically, it is not allowed to call any Redis module API which are client related such as:
         * RedisModule_Reply* API's
         * RedisModule_BlockClient
         * RedisModule_GetCurrentUserName
      
  • ...: Redis命令的实际参数。

成功时返回一个RedisModuleCallReply对象,否则返回NULL,并将errno设置为以下值:

  • EBADF: 错误的格式说明符。
  • EINVAL: 错误的命令参数数量。
  • ENOENT: 命令不存在。
  • EPERM: 在集群实例中操作,键位于非本地槽中。
  • EROFS:在只读状态下发送写命令时,集群实例中的操作。
  • ENETDOWN: 集群实例在集群关闭时的操作。
  • ENOTSUP: 指定的模块上下文中没有ACL用户
  • EACCES: 根据ACL规则,无法执行命令
  • ENOSPC: 不允许写入或拒绝-oom命令
  • ESPIPE: 脚本模式下不允许的命令

示例代码片段:

 reply = RedisModule_Call(ctx,"INCRBY","sc",argv[1],"10");
 if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {
   long long myval = RedisModule_CallReplyInteger(reply);
   // Do something with myval.
 }

此API的文档在此处:https://redis.io/topics/modules-intro

RedisModule_CallReplyProto

const char *RedisModule_CallReplyProto(RedisModuleCallReply *reply,
                                       size_t *len);

自版本起可用: 4.0.0

返回一个指针和长度,指向由返回回复对象的命令返回的协议。

模块数据类型

当字符串DMA或使用现有数据结构不足以满足需求时,可以从头创建新的数据类型并将其导出到Redis。模块必须提供一组回调函数来处理导出的新值(例如,为了提供RDB保存/加载、AOF重写等功能)。在本节中,我们定义了这个API。

RedisModule_CreateDataType

moduleType *RedisModule_CreateDataType(RedisModuleCtx *ctx,
                                       const char *name,
                                       int encver,
                                       void *typemethods_ptr);

自版本起可用: 4.0.0

注册模块导出的新数据类型。参数如下。有关详细文档,请查看模块的API文档,特别是https://redis.io/docs/latest/develop/reference/modules/modules-native-types/

  • name: 一个9个字符的数据类型名称,必须在Redis模块生态系统中唯一。发挥创意...就不会有冲突。使用字符集A-Z a-z 9-0,加上两个"-_"字符。一个好主意是使用,例如-。例如"tree-AntZ"可能意味着"由@antirez提供的树数据结构"。使用大小写字母有助于防止冲突。

  • encver: 编码版本,即模块用于持久化数据的序列化版本。只要"name"匹配,无论使用何种'encver',RDB加载都将分派给类型回调,但模块可以理解它必须加载的编码是否来自模块的旧版本。例如,模块"tree-AntZ"最初使用encver=0。后来升级后,它开始以不同的格式序列化数据,并使用encver=1注册类型。然而,如果rdb_load回调能够检查encver值并相应地采取行动,该模块仍然可以加载旧版本生成的数据。encver必须是0到1023之间的正值。

  • typemethods_ptr 是一个指向 RedisModuleTypeMethods 结构的指针 该结构应填充方法回调和结构版本,如下例所示:

      RedisModuleTypeMethods tm = {
          .version = REDISMODULE_TYPE_METHOD_VERSION,
          .rdb_load = myType_RDBLoadCallBack,
          .rdb_save = myType_RDBSaveCallBack,
          .aof_rewrite = myType_AOFRewriteCallBack,
          .free = myType_FreeCallBack,
    
          // 可选字段
          .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
    
          // 增强的可选字段
          .mem_usage2 = myType_MemUsageCallBack2,
          .free_effort2 = myType_FreeEffortCallBack2,
          .unlink2 = myType_UnlinkCallBack2,
          .copy2 = myType_CopyCallback2,
      }
    
  • rdb_load: 一个回调函数指针,用于从RDB文件加载数据。

  • rdb_save: 一个回调函数指针,用于将数据保存到RDB文件中。

  • aof_rewrite: 一个回调函数指针,用于将数据重写为命令。

  • digest: 用于DEBUG DIGEST的回调函数指针。

  • free: 一个可以释放类型值的回调函数指针。

  • aux_save: 一个回调函数指针,用于将键空间外的数据保存到RDB文件中。 'when' 参数可以是 REDISMODULE_AUX_BEFORE_RDBREDISMODULE_AUX_AFTER_RDB

  • aux_load: 一个回调函数指针,用于从RDB文件中加载键空间外的数据。 类似于 aux_save,成功时返回 REDISMODULE_OK,否则返回 ERR。

  • free_effort: 一个回调函数指针,用于确定模块的内存是否需要延迟回收。模块应返回释放值所涉及的复杂性。例如:将释放多少个指针。请注意,如果返回0,我们将始终执行异步释放。

  • unlink: 一个回调函数指针,用于通知模块该键已被redis从数据库中移除,并可能很快被后台线程释放。请注意,它不会在FLUSHALL/FLUSHDB(同步和异步)时被调用,模块可以使用RedisModuleEvent_FlushDB来挂钩到该事件。

  • copy: 一个回调函数指针,用于复制指定的键。 模块应执行指定值的深度复制并返回它。 此外,还提供了源键和目标键名称的提示。 返回NULL值被视为错误,复制操作将失败。 注意:如果目标键存在并且正在被覆盖,将首先调用复制回调,然后是对被替换值的释放回调。

  • defrag: 一个回调函数指针,用于请求模块对键进行碎片整理。模块应随后迭代指针并调用相关的RedisModule_Defrag*()函数来整理指针或复杂类型的碎片。只要RedisModule_DefragShouldStop()返回零值,模块就应继续迭代,并在完成时返回零值,如果还有工作要做则返回非零值。如果需要做更多工作,可以使用RedisModule_DefragCursorSet()RedisModule_DefragCursorGet()来跟踪不同调用之间的工作。 通常,碎片整理机制调用回调时没有时间限制,因此RedisModule_DefragShouldStop()总是返回零。具有时间限制并提供游标支持的“延迟碎片整理”机制仅用于确定具有显著内部复杂性的键。为了确定这一点,碎片整理机制使用free_effort回调和'active-defrag-max-scan-fields'配置指令。 注意:值作为void**传递,如果顶级值指针被整理并因此更改,函数应更新指针。

  • mem_usage2: 类似于 mem_usage,但提供了 RedisModuleKeyOptCtx 参数 以便可以获取诸如键名和数据库ID等元信息,以及用于大小估计的 sample_size(参见 MEMORY USAGE 命令)。

  • free_effort2: 类似于 free_effort,但提供了 RedisModuleKeyOptCtx 参数 以便可以获取诸如键名和数据库ID等元信息。

  • unlink2: 类似于 unlink,但提供了 RedisModuleKeyOptCtx 参数 以便可以获取诸如键名和数据库ID等元信息。

  • copy2: 类似于 copy,但提供了 RedisModuleKeyOptCtx 参数 以便可以获取诸如键名和数据库ID等元信息。

  • aux_save2: 类似于 aux_save,但有一些小的语义变化,如果模块在此回调中不保存任何内容,则不会将此辅助字段的数据写入RDB,即使模块未加载,也可以加载RDB。

注意:模块名称 "AAAAAAAAA" 是保留的,会导致错误,而且它本身也很糟糕。

如果在RedisModule_OnLoad()函数之外调用RedisModule_CreateDataType(), 或者已经有一个模块注册了相同名称的类型, 或者模块名称或encver无效,则返回NULL。 否则,新类型将被注册到Redis中,并返回一个RedisModuleType类型的引用: 函数的调用者应将该引用存储到全局变量中,以便在模块类型API中将来使用, 因为单个模块可以注册多个类型。 示例代码片段:

 static RedisModuleType *BalancedTreeType;

 int RedisModule_OnLoad(RedisModuleCtx *ctx) {
     // some code here ...
     BalancedTreeType = RedisModule_CreateDataType(...);
 }

RedisModule_ModuleTypeSetValue

int RedisModule_ModuleTypeSetValue(RedisModuleKey *key,
                                   moduleType *mt,
                                   void *value);

自版本起可用: 4.0.0

如果键是开放写入的,将指定的模块类型对象设置为键的值,删除任何旧值。 成功时返回REDISMODULE_OK。如果键未开放写入或存在活动迭代器,则返回REDISMODULE_ERR

RedisModule_ModuleTypeGetType

moduleType *RedisModule_ModuleTypeGetType(RedisModuleKey *key);

自版本起可用: 4.0.0

假设RedisModule_KeyType()在键上返回了REDISMODULE_KEYTYPE_MODULE,则返回存储在键中的值的模块类型指针。

如果键为NULL,未与模块类型关联,或为空,则返回NULL。

RedisModule_ModuleTypeGetValue

void *RedisModule_ModuleTypeGetValue(RedisModuleKey *key);

自版本起可用: 4.0.0

假设RedisModule_KeyType()在键上返回了REDISMODULE_KEYTYPE_MODULE,则返回存储在键中的模块类型低级别值,该值由用户通过RedisModule_ModuleTypeSetValue()设置。

如果键为NULL,未与模块类型关联,或为空,则返回NULL。

RDB加载和保存函数

RedisModule_IsIOError

int RedisModule_IsIOError(RedisModuleIO *io);

自版本起可用: 6.0.0

如果之前的任何IO API失败,则返回true。 对于Load* API,必须首先使用RedisModule_SetModuleOptions设置REDISMODULE_OPTIONS_HANDLE_IO_ERRORS标志。

RedisModule_SaveUnsigned

void RedisModule_SaveUnsigned(RedisModuleIO *io, uint64_t value);

自版本起可用: 4.0.0

将一个无符号的64位值保存到RDB文件中。此函数应仅在实现新数据类型的模块的rdb_save方法的上下文中调用。

RedisModule_LoadUnsigned

uint64_t RedisModule_LoadUnsigned(RedisModuleIO *io);

自版本起可用: 4.0.0

从RDB文件中加载一个无符号的64位值。此函数应仅在实现新数据类型的模块的rdb_load方法上下文中调用。

RedisModule_SaveSigned

void RedisModule_SaveSigned(RedisModuleIO *io, int64_t value);

自版本起可用: 4.0.0

类似于 RedisModule_SaveUnsigned(),但用于有符号的64位值。

RedisModule_LoadSigned

int64_t RedisModule_LoadSigned(RedisModuleIO *io);

自版本起可用: 4.0.0

类似于 RedisModule_LoadUnsigned(),但用于有符号的64位值。

RedisModule_SaveString

void RedisModule_SaveString(RedisModuleIO *io, RedisModuleString *s);

自版本起可用: 4.0.0

在模块类型的rdb_save方法上下文中,将字符串保存到RDB文件中,输入为RedisModuleString

字符串可以稍后使用RedisModule_LoadString()或其他期望在RDB文件中包含序列化字符串的Load系列函数加载。

RedisModule_SaveStringBuffer

void RedisModule_SaveStringBuffer(RedisModuleIO *io,
                                  const char *str,
                                  size_t len);

自版本起可用: 4.0.0

类似于 RedisModule_SaveString(),但接受一个原始的 C 指针和长度作为输入。

RedisModule_LoadString

RedisModuleString *RedisModule_LoadString(RedisModuleIO *io);

自版本起可用: 4.0.0

在模块数据类型的rdb_load方法上下文中,从RDB文件加载一个字符串,该字符串之前是通过RedisModule_SaveString()函数家族保存的。

返回的字符串是一个新分配的RedisModuleString对象,用户应在某个时刻通过调用RedisModule_FreeString()来释放它。

如果数据结构不将字符串存储为RedisModuleString对象, 可以使用类似的函数RedisModule_LoadStringBuffer()代替。

RedisModule_LoadStringBuffer

char *RedisModule_LoadStringBuffer(RedisModuleIO *io, size_t *lenptr);

自版本起可用: 4.0.0

类似于 RedisModule_LoadString(),但返回一个使用 RedisModule_Alloc() 分配的堆分配字符串,可以使用 RedisModule_Realloc()RedisModule_Free() 调整大小或释放。

字符串的大小存储在'*lenptr'中,如果不为NULL。 返回的字符串不会自动以NULL结尾,它是按照RDB文件中存储的方式精确加载的。

RedisModule_SaveDouble

void RedisModule_SaveDouble(RedisModuleIO *io, double value);

自版本起可用: 4.0.0

在模块数据类型的rdb_save方法上下文中,将一个双精度值保存到RDB文件中。该双精度值可以是一个有效的数字、NaN或无穷大。可以使用RedisModule_LoadDouble()重新加载该值。

RedisModule_LoadDouble

double RedisModule_LoadDouble(RedisModuleIO *io);

自版本起可用: 4.0.0

在模块数据类型的rdb_save方法上下文中,加载由RedisModule_SaveDouble()保存的双精度值。

RedisModule_SaveFloat

void RedisModule_SaveFloat(RedisModuleIO *io, float value);

自版本起可用: 4.0.0

在模块数据类型的rdb_save方法上下文中,将一个浮点数值保存到RDB文件中。该浮点数可以是一个有效的数字、NaN或无穷大。可以使用RedisModule_LoadFloat()重新加载该值。

RedisModule_LoadFloat

float RedisModule_LoadFloat(RedisModuleIO *io);

自版本起可用: 4.0.0

在模块数据类型的rdb_save方法上下文中,加载由RedisModule_SaveFloat()保存的浮点值。

RedisModule_SaveLongDouble

void RedisModule_SaveLongDouble(RedisModuleIO *io, long double value);

自版本起可用: 6.0.0

在模块数据类型的rdb_save方法上下文中,将一个长双精度值保存到RDB文件中。该双精度值可以是一个有效数字、NaN或无穷大。可以使用RedisModule_LoadLongDouble()重新加载该值。

RedisModule_LoadLongDouble

long double RedisModule_LoadLongDouble(RedisModuleIO *io);

自版本起可用: 6.0.0

在模块数据类型的rdb_save方法上下文中,加载由RedisModule_SaveLongDouble()保存的长双精度值。

关键摘要API(用于模块类型的DEBUG DIGEST接口)

RedisModule_DigestAddStringBuffer

void RedisModule_DigestAddStringBuffer(RedisModuleDigest *md,
                                       const char *ele,
                                       size_t len);

自版本起可用: 4.0.0

向摘要中添加一个新元素。这个函数可以多次调用,依次为构成给定数据结构的所有元素添加。在所有总是按给定顺序添加的元素都添加完毕后,最终必须调用RedisModule_DigestEndSequence。有关更多信息,请参阅Redis模块数据类型文档。不过,这里有一个使用Redis数据类型作为示例的快速示例。

要添加一系列无序元素(例如在Redis集合的情况下),使用的模式是:

foreach element {
    AddElement(element);
    EndSequence();
}

因为集合是无序的,所以每个添加的元素都有一个不依赖于其他元素的位置。然而,如果我们的元素是成对有序的,比如哈希的字段-值对,那么应该使用:

foreach key,value {
    AddElement(key);
    AddElement(value);
    EndSequence();
}

因为键和值将始终按照上述顺序排列,而单个键值对可以出现在Redis哈希中的任何位置。

一个有序元素的列表将使用以下方式实现:

foreach element {
    AddElement(element);
}
EndSequence();

RedisModule_DigestAddLongLong

void RedisModule_DigestAddLongLong(RedisModuleDigest *md, long long ll);

自版本起可用: 4.0.0

类似于 RedisModule_DigestAddStringBuffer(),但接受一个 long long 作为输入,在将其添加到摘要之前会将其转换为字符串。

RedisModule_DigestEndSequence

void RedisModule_DigestEndSequence(RedisModuleDigest *md);

自版本起可用: 4.0.0

请参阅RedisModule_DigestAddElement()的文档。

RedisModule_LoadDataTypeFromStringEncver

void *RedisModule_LoadDataTypeFromStringEncver(const RedisModuleString *str,
                                               const moduleType *mt,
                                               int encver);

自版本起可用: 7.0.0

解码模块数据类型 'mt' 的序列化表示,使用特定的编码版本 'encver' 从字符串 'str' 中解码,并返回一个新分配的值,如果解码失败则返回 NULL。

此调用基本上重用了模块数据类型实现的rdb_load回调,以允许模块任意序列化/反序列化键,类似于Redis的'DUMP'和'RESTORE'命令的实现方式。

模块通常应使用REDISMODULE_OPTIONS_HANDLE_IO_ERRORS标志,并确保反序列化代码正确检查和处理IO错误(释放分配的缓冲区并返回NULL)。

如果不这样做,Redis 将通过生成错误消息并终止进程来处理损坏(或只是截断)的序列化数据。

RedisModule_LoadDataTypeFromString

void *RedisModule_LoadDataTypeFromString(const RedisModuleString *str,
                                         const moduleType *mt);

自版本起可用: 6.0.0

类似于RedisModule_LoadDataTypeFromStringEncver,API的原始版本,保留以保持向后兼容性。

RedisModule_SaveDataTypeToString

RedisModuleString *RedisModule_SaveDataTypeToString(RedisModuleCtx *ctx,
                                                    void *data,
                                                    const moduleType *mt);

自版本起可用: 6.0.0

将模块数据类型 'mt' 的值 'data' 编码为序列化形式,并将其作为新分配的 RedisModuleString 返回。

此调用基本上重用了模块数据类型实现的rdb_save回调,以允许模块任意序列化/反序列化键,类似于Redis的'DUMP'和'RESTORE'命令的实现方式。

RedisModule_GetKeyNameFromDigest

const RedisModuleString *RedisModule_GetKeyNameFromDigest(RedisModuleDigest *dig);

自版本起可用: 7.0.0

返回当前正在处理的键的名称。

RedisModule_GetDbIdFromDigest

int RedisModule_GetDbIdFromDigest(RedisModuleDigest *dig);

自版本起可用: 7.0.0

返回当前正在处理的键的数据库ID。

模块数据类型的AOF API

RedisModule_EmitAOF

void RedisModule_EmitAOF(RedisModuleIO *io,
                         const char *cmdname,
                         const char *fmt,
                         ...);

自版本起可用: 4.0.0

在AOF重写过程中向AOF发出一个命令。此函数仅在模块导出的数据类型的aof_rewrite方法上下文中调用。该命令的工作方式与RedisModule_Call()完全相同,参数传递方式相同,但它不返回任何内容,因为错误处理由Redis本身执行。

IO 上下文处理

RedisModule_GetKeyNameFromIO

const RedisModuleString *RedisModule_GetKeyNameFromIO(RedisModuleIO *io);

自以下版本可用: 5.0.5

返回当前正在处理的键的名称。 不能保证键名称始终可用,因此这可能返回NULL。

RedisModule_GetKeyNameFromModuleKey

const RedisModuleString *RedisModule_GetKeyNameFromModuleKey(RedisModuleKey *key);

自版本起可用: 6.0.0

返回一个带有来自RedisModuleKey的键名称的RedisModuleString

RedisModule_GetDbIdFromModuleKey

int RedisModule_GetDbIdFromModuleKey(RedisModuleKey *key);

自版本起可用: 7.0.0

返回来自RedisModuleKey的键的数据库ID。

RedisModule_GetDbIdFromIO

int RedisModule_GetDbIdFromIO(RedisModuleIO *io);

自版本起可用: 7.0.0

返回当前正在处理的键的数据库ID。 不能保证此信息始终可用,因此可能返回-1。

日志记录

RedisModule_Log

void RedisModule_Log(RedisModuleCtx *ctx,
                     const char *levelstr,
                     const char *fmt,
                     ...);

自版本起可用: 4.0.0

生成一条日志消息到标准的Redis日志中,格式接受类似printf的说明符,而level是一个描述日志级别的字符串,当发出日志时必须使用以下之一:

  • "调试" (REDISMODULE_LOGLEVEL_DEBUG)
  • "详细" (REDISMODULE_LOGLEVEL_VERBOSE)
  • "通知" (REDISMODULE_LOGLEVEL_NOTICE)
  • "警告" (REDISMODULE_LOGLEVEL_WARNING)

如果指定的日志级别无效,默认使用详细模式。 此函数能够发出的日志行长度有一个固定的限制,这个限制没有具体说明,但保证超过几行文本。

如果无法在调用者的上下文中提供ctx参数,例如线程或回调,则ctx参数可能为NULL,在这种情况下,将使用通用的“模块”代替模块名称。

RedisModule_LogIOError

void RedisModule_LogIOError(RedisModuleIO *io,
                            const char *levelstr,
                            const char *fmt,
                            ...);

自版本起可用: 4.0.0

记录来自RDB / AOF序列化回调的错误。

当回调函数由于某些关键原因无法加载或保存数据时,应使用此函数向调用者返回关键错误。

RedisModule__Assert

void RedisModule__Assert(const char *estr, const char *file, int line);

自版本起可用: 6.0.0

类似Redis的断言函数。

建议使用宏 RedisModule_Assert(expression),而不是直接调用此函数。

断言失败将关闭服务器并生成与Redis本身生成的信息完全相同的日志信息。

RedisModule_LatencyAddSample

void RedisModule_LatencyAddSample(const char *event, mstime_t latency);

自版本起可用: 6.0.0

允许向延迟监视器添加事件,以便通过LATENCY命令进行观察。如果延迟小于配置的延迟监视器阈值,则跳过该调用。

阻止客户端访问模块

有关模块中阻塞命令的指南,请参阅 https://redis.io/docs/latest/develop/reference/modules/modules-blocking-ops/

RedisModule_RegisterAuthCallback

void RedisModule_RegisterAuthCallback(RedisModuleCtx *ctx,
                                      RedisModuleAuthCallback cb);

自版本起可用: 7.2.0

此API注册一个回调,除了基于密码的正常认证外,还会执行该回调。 可以在不同的模块中注册多个回调。当一个模块被卸载时,所有由它注册的认证回调都会被取消注册。 当调用AUTH/HELLO(提供AUTH字段)命令时,会尝试这些回调(按最近注册的顺序)。 回调将使用模块上下文以及用户名和密码调用,并预期采取以下操作之一: (1) 认证 - 使用RedisModule_AuthenticateClient* API并返回REDISMODULE_AUTH_HANDLED。 这将立即成功结束认证链并添加OK回复。 (2) 拒绝认证 - 返回REDISMODULE_AUTH_HANDLED而不进行认证或阻止客户端。可选地,可以设置err为自定义错误消息,err将由服务器自动释放。 这将立即以不成功结束认证链并添加ERR回复。 (3) 阻止客户端进行认证 - 使用RedisModule_BlockClientOnAuth API并返回REDISMODULE_AUTH_HANDLED。在这里,客户端将被阻止,直到使用RedisModule_UnblockClient API,这将触发认证回复回调(通过RedisModule_BlockClientOnAuth提供)。 在此回复回调中,模块应认证、拒绝或跳过处理认证。 (4) 跳过处理认证 - 返回REDISMODULE_AUTH_NOT_HANDLED而不阻止客户端。这将允许引擎尝试下一个模块认证回调。 如果没有回调进行认证或拒绝认证,则将尝试基于密码的认证,并相应地认证或添加失败日志并回复客户端。

注意:如果客户端在阻塞模块认证过程中断开连接,则该次AUTH或HELLO命令将不会在INFO命令统计中被跟踪。

以下是如何使用基于非阻塞模块的身份验证的示例:

 int auth_cb(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *password, RedisModuleString **err) {
     const char *user = RedisModule_StringPtrLen(username, NULL);
     const char *pwd = RedisModule_StringPtrLen(password, NULL);
     if (!strcmp(user,"foo") && !strcmp(pwd,"valid_password")) {
         RedisModule_AuthenticateClientWithACLUser(ctx, "foo", 3, NULL, NULL, NULL);
         return REDISMODULE_AUTH_HANDLED;
     }

     else if (!strcmp(user,"foo") && !strcmp(pwd,"wrong_password")) {
         RedisModuleString *log = RedisModule_CreateString(ctx, "Module Auth", 11);
         RedisModule_ACLAddLogEntryByUserName(ctx, username, log, REDISMODULE_ACL_LOG_AUTH);
         RedisModule_FreeString(ctx, log);
         const char *err_msg = "Auth denied by Misc Module.";
         *err = RedisModule_CreateString(ctx, err_msg, strlen(err_msg));
         return REDISMODULE_AUTH_HANDLED;
     }
     return REDISMODULE_AUTH_NOT_HANDLED;
  }

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

RedisModule_BlockClient

RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx,
                                                  RedisModuleCmdFunc reply_callback,
                                                  ;

自版本起可用: 4.0.0

在阻塞命令的上下文中阻塞一个客户端,返回一个句柄,该句柄将在稍后用于通过调用RedisModule_UnblockClient()来解除客户端的阻塞。参数指定了回调函数和客户端被解除阻塞的超时时间。

回调函数在以下上下文中被调用:

reply_callback:   called after a successful RedisModule_UnblockClient()
                  call in order to reply to the client and unblock it.

timeout_callback: called when the timeout is reached or if `CLIENT UNBLOCK`
                  is invoked, in order to send an error to the client.

free_privdata:    called in order to free the private data that is passed
                  by RedisModule_UnblockClient() call.

注意:对于每个被阻塞的客户端,都应调用RedisModule_UnblockClient,即使客户端被杀死、超时或断开连接。如果不这样做,将导致内存泄漏。

在某些情况下,RedisModule_BlockClient() 无法使用:

  1. 如果客户端是一个Lua脚本。
  2. 如果客户端正在执行一个MULTI块。

在这些情况下,调用RedisModule_BlockClient()不会阻塞客户端,而是会产生一个特定的错误回复。

一个注册了timeout_callback函数的模块也可以使用CLIENT UNBLOCK命令解除阻塞,这将触发超时回调。如果没有注册回调函数,那么被阻塞的客户端将被视为未处于阻塞状态,并且CLIENT UNBLOCK将返回零值。

测量后台时间:默认情况下,阻塞命令中花费的时间不计入总命令持续时间。要包含此类时间,您应该在阻塞命令的后台工作中使用RedisModule_BlockedClientMeasureTimeStart()RedisModule_BlockedClientMeasureTimeEnd()一次或多次。

RedisModule_BlockClientOnAuth

RedisModuleBlockedClient *RedisModule_BlockClientOnAuth(RedisModuleCtx *ctx,
                                                        RedisModuleAuthCallback reply_callback,
                                                        ;

自版本起可用: 7.2.0

在后台阻止当前客户端进行模块认证。如果客户端上没有进行模块认证,API 将返回 NULL。否则,客户端将被阻止,并返回 RedisModule_BlockedClient,类似于 RedisModule_BlockClient API。 注意:仅在模块认证回调的上下文中使用此 API。

RedisModule_BlockClientGetPrivateData

void *RedisModule_BlockClientGetPrivateData(RedisModuleBlockedClient *blocked_client);

自版本起可用: 7.2.0

获取之前在阻塞客户端上设置的私有数据

RedisModule_BlockClientSetPrivateData

void RedisModule_BlockClientSetPrivateData(RedisModuleBlockedClient *blocked_client,
                                           void *private_data);

自版本起可用: 7.2.0

在阻塞的客户端上设置私有数据

RedisModule_BlockClientOnKeys

RedisModuleBlockedClient *RedisModule_BlockClientOnKeys(RedisModuleCtx *ctx,
                                                        RedisModuleCmdFunc reply_callback,
                                                        ;

自版本起可用: 6.0.0

此调用类似于RedisModule_BlockClient(),然而在这种情况下,我们不仅阻塞客户端,还要求Redis在特定键“准备就绪”时自动解除阻塞,即包含更多数据。

基本上,这与典型的Redis命令通常所做的类似,比如BLPOP或BZPOPMAX:如果客户端不能立即得到服务,它就会被阻塞,然后当键接收到新数据(例如列表推送)时,客户端会被解除阻塞并得到服务。

然而,在这个模块API的情况下,当客户端被解除阻塞时?

  1. 如果您在具有阻塞操作的类型(如列表、排序集、流等)的键上阻塞,一旦相关键被通常解除该类型原生阻塞操作的操作所针对,客户端可能会被解除阻塞。因此,如果我们在列表键上阻塞,RPUSH 命令可能会解除我们客户端的阻塞,依此类推。
  2. 如果您正在实现自己的原生数据类型,或者除了“1”之外还想添加新的非阻塞条件,您可以调用模块API RedisModule_SignalKeyAsReady()

无论如何,我们不能仅仅因为键被标记为就绪就确定客户端应该被解除阻塞:例如,后续操作可能会更改键,或者在此之前的队列中的客户端可以被服务,修改键并再次使其为空。因此,当客户端被RedisModule_BlockClientOnKeys()阻塞时,回复回调不会在RedisModule_UnblockClient()被调用后立即调用,而是每次键被标记为就绪时:如果回复回调可以服务客户端,它返回REDISMODULE_OK并且客户端被解除阻塞,否则它将返回REDISMODULE_ERR,我们稍后再试。

回复回调可以通过调用API RedisModule_GetBlockedClientReadyKey()访问被标记为准备就绪的键,该API返回键的字符串名称作为RedisModuleString对象。

多亏了这个系统,我们可以设置复杂的阻塞场景,比如只有在列表包含至少5个项目或其他更复杂的逻辑时,才能解除对客户的阻塞。

请注意,与RedisModule_BlockClient()的另一个区别是,在这里我们直接在阻塞客户端时传递私有数据:它将在稍后的回复回调中可访问。通常,当使用RedisModule_BlockClient()阻塞时,回复客户端的私有数据是在调用RedisModule_UnblockClient()时传递的,但在这里解阻塞是由Redis本身执行的,因此我们需要事先拥有一些私有数据。私有数据用于存储有关您正在实现的特定解阻塞操作的任何信息。此类信息将使用用户提供的free_privdata回调进行释放。

然而,回复回调将能够访问命令的参数向量,因此通常不需要私有数据。

注意:在正常情况下,不应该对阻塞在键上的客户端调用RedisModule_UnblockClient(键将变为就绪或发生超时)。如果出于某种原因确实想要调用RedisModule_UnblockClient,这是可能的:客户端将被视为已超时(在这种情况下,您必须实现超时回调)。

RedisModule_BlockClientOnKeysWithFlags

RedisModuleBlockedClient *RedisModule_BlockClientOnKeysWithFlags(RedisModuleCtx *ctx,
                                                                 RedisModuleCmdFunc reply_callback,
                                                                 ;

自版本起可用: 7.2.0

RedisModule_BlockClientOnKeys相同,但可以接受REDISMODULE_BLOCK_*标志 可以是REDISMODULE_BLOCK_UNBLOCK_DEFAULT,这意味着默认行为(与调用RedisModule_BlockClientOnKeys相同)

标志是这些的位掩码:

  • REDISMODULE_BLOCK_UNBLOCK_DELETED: 如果任何keys被删除,客户端应该被唤醒。 主要用于需要键存在的命令(如XREADGROUP)

RedisModule_SignalKeyAsReady

void RedisModule_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key);

自版本起可用: 6.0.0

此函数用于可能解除在键上阻塞的客户端,使用RedisModule_BlockClientOnKeys()。当调用此函数时,所有因该键而阻塞的客户端将调用其reply_callback

RedisModule_UnblockClient

int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata);

自版本起可用: 4.0.0

解除被RedisModule_BlockedClient阻塞的客户端。这将触发回复回调函数被调用,以便向客户端发送回复。 'reply'回调函数可以访问'privdata'参数,因此此函数的调用者可以传递任何需要的值,以便实际向客户端发送回复。

'privdata' 的一个常见用途是一个线程,它计算需要传递给客户端的内容,包括但不限于一些计算缓慢的回复或通过网络获取的回复。

注意1:此函数可以从模块生成的线程中调用。

注意2:当我们使用API RedisModule_BlockClientOnKeys() 解锁一个因键而被阻塞的客户端时,这里的privdata参数不会被使用。使用此API解锁因键而被阻塞的客户端仍然需要客户端获得一些回复,因此该函数将使用“超时”处理程序来实现这一点(在RedisModule_BlockClientOnKeys()中提供的privdata可以通过RedisModule_GetBlockedClientPrivateData从超时回调中访问)。

RedisModule_AbortBlock

int RedisModule_AbortBlock(RedisModuleBlockedClient *bc);

自版本起可用: 4.0.0

中止一个被阻塞的客户端阻塞操作:客户端将被解除阻塞,而不会触发任何回调。

RedisModule_SetDisconnectCallback

void RedisModule_SetDisconnectCallback(RedisModuleBlockedClient *bc,
                                       RedisModuleDisconnectFunc callback);

自版本起可用: 5.0.0

设置一个回调函数,当被阻塞的客户端在模块有机会调用RedisModule_UnblockClient()之前断开连接时,将调用该回调函数。

通常你在这里想要做的是清理你的模块状态,这样你就可以安全地调用RedisModule_UnblockClient(),否则如果超时时间很长,客户端将永远保持阻塞状态。

注释:

  1. 在这里调用Reply*系列函数是不安全的,也是无用的,因为客户端已经断开连接。

  2. 如果客户端由于超时而断开连接,则不会调用此回调。在这种情况下,客户端会自动解除阻塞,并调用超时回调。

RedisModule_IsBlockedReplyRequest

int RedisModule_IsBlockedReplyRequest(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

如果调用模块命令以填充被阻塞客户端的回复,则返回非零值。

RedisModule_IsBlockedTimeoutRequest

int RedisModule_IsBlockedTimeoutRequest(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

如果调用了一个模块命令以填充超时的被阻塞客户端的回复,则返回非零值。

RedisModule_GetBlockedClientPrivateData

void *RedisModule_GetBlockedClientPrivateData(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

获取由RedisModule_UnblockClient()设置的私有数据集

RedisModule_GetBlockedClientReadyKey

RedisModuleString *RedisModule_GetBlockedClientReadyKey(RedisModuleCtx *ctx);

自版本起可用: 6.0.0

获取在客户端被RedisModule_BlockClientOnKeys()阻塞时,当回复回调被调用时准备好的键。

RedisModule_GetBlockedClientHandle

RedisModuleBlockedClient *RedisModule_GetBlockedClientHandle(RedisModuleCtx *ctx);

自版本起可用: 5.0.0

获取与给定上下文关联的被阻塞客户端。 这在被阻塞客户端的回复和超时回调中非常有用, 因为有时模块会持有被阻塞客户端的句柄引用, 并希望清理它。

RedisModule_BlockedClientDisconnected

int RedisModule_BlockedClientDisconnected(RedisModuleCtx *ctx);

自版本起可用: 5.0.0

如果调用被阻塞客户端的空闲回调时,客户端解除阻塞的原因是它在被阻塞时断开连接,则返回true。

线程安全上下文

RedisModule_GetThreadSafeContext

RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc);

自版本起可用: 4.0.0

返回一个上下文,该上下文可以在线程内部使用,以便使用某些模块API进行Redis上下文调用。如果'bc'不为NULL,则模块将绑定到一个被阻塞的客户端,并且可以使用RedisModule_Reply*系列函数来累积回复,以便在客户端解除阻塞时使用。否则,线程安全上下文将与特定客户端分离。

要调用非回复API,必须准备线程安全上下文:

RedisModule_ThreadSafeContextLock(ctx);
... make your call here ...
RedisModule_ThreadSafeContextUnlock(ctx);

在使用RedisModule_Reply*函数时,如果创建上下文时使用了阻塞客户端,则不需要这样做,否则根本不应该进行任何RedisModule_Reply*调用。

注意:如果您正在创建一个独立的线程安全上下文(bc 为 NULL), 考虑使用 RedisModule_GetDetachedThreadSafeContext,它还将保留 模块 ID,因此对于日志记录更有用。

RedisModule_GetDetachedThreadSafeContext

RedisModuleCtx *RedisModule_GetDetachedThreadSafeContext(RedisModuleCtx *ctx);

自以下版本可用: 6.0.9

返回一个独立的线程安全上下文,该上下文不与任何特定的阻塞客户端关联,但与模块的上下文关联。

这对于希望长期保持全局上下文的模块非常有用,例如用于日志记录等目的。

RedisModule_FreeThreadSafeContext

void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

释放一个线程安全的上下文。

RedisModule_ThreadSafeContextLock

void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

在执行线程安全的API调用之前获取服务器锁。 当有阻塞的客户端连接到线程安全上下文时,RedisModule_Reply*调用不需要这样做。

RedisModule_ThreadSafeContextTryLock

int RedisModule_ThreadSafeContextTryLock(RedisModuleCtx *ctx);

自版本起可用: 6.0.8

类似于RedisModule_ThreadSafeContextLock,但如果服务器锁已被获取,此函数不会阻塞。

如果成功(获取锁),则返回REDISMODULE_OK, 否则返回REDISMODULE_ERR并相应地设置errno。

RedisModule_ThreadSafeContextUnlock

void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx);

自版本起可用: 4.0.0

在线程安全的API调用执行后释放服务器锁。

模块键空间通知 API

RedisModule_SubscribeToKeyspaceEvents

int RedisModule_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx,
                                          int types,
                                          RedisModuleNotificationFunc callback);

自以下版本可用: 4.0.9

订阅键空间通知。这是键空间通知API的低级版本。模块可以注册回调,以便在键空间事件发生时收到通知。

通知事件按其类型(字符串事件、集合事件等)进行过滤,订阅者回调仅接收与特定事件类型掩码匹配的事件。

当使用RedisModule_SubscribeToKeyspaceEvents订阅通知时,模块必须提供一个事件类型掩码,表示订阅者感兴趣的事件。这可以是以下任何标志的ORed掩码:

  • REDISMODULE_NOTIFY_GENERIC: 通用命令,如 DEL, EXPIRE, RENAME
  • REDISMODULE_NOTIFY_STRING: 字符串事件
  • REDISMODULE_NOTIFY_LIST: 列表事件
  • REDISMODULE_NOTIFY_SET: 集合事件
  • REDISMODULE_NOTIFY_HASH: 哈希事件
  • REDISMODULE_NOTIFY_ZSET: 有序集合事件
  • REDISMODULE_NOTIFY_EXPIRED: 过期事件
  • REDISMODULE_NOTIFY_EVICTED: 驱逐事件
  • REDISMODULE_NOTIFY_STREAM: 流事件
  • REDISMODULE_NOTIFY_MODULE: 模块类型事件
  • REDISMODULE_NOTIFY_KEYMISS: 键未命中事件 注意,键未命中事件是唯一一种 从读命令中触发的事件。 在此通知中执行带有写命令的RedisModule_Call是错误的,并且不推荐这样做。它会导致触发事件的读命令被复制到AOF/副本中。
  • REDISMODULE_NOTIFY_ALL: 所有事件(不包括 REDISMODULE_NOTIFY_KEYMISS
  • REDISMODULE_NOTIFY_LOADED: 一个仅对模块可用的特殊通知,表示该键已从持久化中加载。 注意,当此事件触发时,给定的键不能被保留,请使用 RedisModule_CreateStringFromString 代替。

我们不区分键事件和键空间事件,由模块根据键来过滤执行的操作。

订阅者签名是:

int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type,
                                    const char *event,
                                    RedisModuleString *key);

type 是事件类型位,必须与注册时给定的掩码匹配。事件字符串是实际执行的命令,而 key 是相关的 Redis 键。

通知回调会使用一个无法向客户端发送任何内容的redis上下文执行,并且将事件发生的数据库编号作为其选定的数据库编号。

请注意,为了使模块通知工作,不需要在redis.conf中启用通知。

警告:通知回调是以同步方式执行的,因此通知回调必须快速执行,否则会减慢Redis的速度。如果需要执行长时间的操作,请使用线程来卸载它们。

此外,通知是同步执行的这一事实意味着通知代码将在Redis逻辑(命令逻辑、驱逐、过期)中间执行。在逻辑运行时更改键空间是危险的,不推荐这样做。为了通过写操作对键空间事件做出反应,请参考RedisModule_AddPostNotificationJob

更多信息请参见 https://redis.io/topics/notifications

RedisModule_AddPostNotificationJob

int RedisModule_AddPostNotificationJob(RedisModuleCtx *ctx,
                                       RedisModulePostNotificationJobFunc callback,
                                       void *privdata,
                                       void (*free_privdata)(void*));

自版本起可用: 7.2.0

在键空间通知回调中运行时,执行任何写操作是危险且强烈不推荐的(参见RedisModule_SubscribeToKeyspaceEvents)。为了在这种情况下仍然执行写操作,Redis提供了RedisModule_AddPostNotificationJob API。该API允许注册一个作业回调,Redis将在满足以下条件时调用该回调:

  1. 执行任何写操作都是安全的。
  2. 该任务将与键空间通知一起原子性地调用。

注意,一个作业可能会触发键空间通知,这些通知又会触发更多的作业。 这引发了进入无限循环的担忧,我们将无限循环视为需要在模块中修复的逻辑错误,尝试通过停止执行来防止无限循环可能会导致功能正确性的违反,因此Redis不会尝试保护模块免受无限循环的影响。

'free_pd' 可以为 NULL,在这种情况下将不会被使用。

成功时返回 REDISMODULE_OK,如果在从磁盘(AOF 或 RDB)加载数据时调用或实例是只读副本,则返回 REDISMODULE_ERR

RedisModule_GetNotifyKeyspaceEvents

int RedisModule_GetNotifyKeyspaceEvents(void);

自版本起可用: 6.0.0

获取配置的notify-keyspace-events位图(可用于RedisModuleNotificationFunc中的额外过滤)

RedisModule_NotifyKeyspaceEvent

int RedisModule_NotifyKeyspaceEvent(RedisModuleCtx *ctx,
                                    int type,
                                    const char *event,
                                    RedisModuleString *key);

自版本起可用: 6.0.0

将notifyKeyspaceEvent暴露给模块

模块集群 API

RedisModule_RegisterClusterMessageReceiver

void RedisModule_RegisterClusterMessageReceiver(RedisModuleCtx *ctx,
                                                uint8_t type,
                                                RedisModuleClusterMessageReceiver callback);

自版本起可用: 5.0.0

为类型为'type'的集群消息注册一个回调接收器。如果已经有一个注册的回调,这将用提供的回调函数替换它,否则如果回调设置为NULL并且已经有一个此函数的回调,则取消注册回调(因此此API调用也用于删除接收器)。

RedisModule_SendClusterMessage

int RedisModule_SendClusterMessage(RedisModuleCtx *ctx,
                                   const char *target_id,
                                   uint8_t type,
                                   const char *msg,
                                   uint32_t len);

自版本起可用: 5.0.0

如果target为NULL,则向集群中的所有节点发送消息,否则发送到指定的目标,该目标是一个REDISMODULE_NODE_ID_LEN字节的节点ID,由接收回调或节点迭代函数返回。

如果消息成功发送,函数返回REDISMODULE_OK, 否则如果节点未连接或该节点ID未映射到任何已知的集群节点,则返回REDISMODULE_ERR

RedisModule_GetClusterNodesList

char **RedisModule_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes);

自版本起可用: 5.0.0

返回一个字符串指针数组,每个字符串指针指向一个集群节点ID,该ID正好是REDISMODULE_NODE_ID_LEN字节(没有任何空终止符)。返回的节点ID数量存储在*numnodes中。然而,如果此函数由未在启用Redis集群的Redis实例上运行的模块调用,则返回NULL。

返回的ID可以与RedisModule_GetClusterNodeInfo()一起使用,以便获取有关单个节点的更多信息。

此函数返回的数组必须使用函数 RedisModule_FreeClusterNodesList()来释放。

示例:

size_t count, j;
char **ids = RedisModule_GetClusterNodesList(ctx,&count);
for (j = 0; j < count; j++) {
    RedisModule_Log(ctx,"notice","Node %.*s",
        REDISMODULE_NODE_ID_LEN,ids[j]);
}
RedisModule_FreeClusterNodesList(ids);

RedisModule_FreeClusterNodesList

void RedisModule_FreeClusterNodesList(char **ids);

自版本起可用: 5.0.0

释放通过RedisModule_GetClusterNodesList获取的节点列表。

RedisModule_GetMyClusterID

const char *RedisModule_GetMyClusterID(void);

自版本起可用: 5.0.0

返回此节点ID(REDISMODULE_CLUSTER_ID_LEN 字节)或如果集群被禁用则返回NULL。

RedisModule_GetClusterSize

size_t RedisModule_GetClusterSize(void);

自版本起可用: 5.0.0

返回集群中的节点数量,无论它们的状态如何(握手、无地址等),因此活跃节点的数量可能实际上更少,但不会超过这个数量。如果实例不在集群模式下,则返回零。

RedisModule_GetClusterNodeInfo

int RedisModule_GetClusterNodeInfo(RedisModuleCtx *ctx,
                                   const char *id,
                                   char *ip,
                                   char *master_id,
                                   int *port,
                                   int *flags);

自版本起可用: 5.0.0

为具有指定'id'的节点填充指定的信息,然后返回REDISMODULE_OK。否则,如果节点ID的格式无效或从本地节点的角度来看节点ID不存在,则返回REDISMODULE_ERR

参数 ipmaster_idportflags 可以为 NULL,以防我们不需要填充某些信息。如果指定了 ipmaster_id(仅在实例是从属时填充),它们指向至少持有 REDISMODULE_NODE_ID_LEN 字节的缓冲区。作为 ipmaster_id 写回的字符串不以 null 结尾。

报告的标志列表如下:

  • REDISMODULE_NODE_MYSELF: 这个节点
  • REDISMODULE_NODE_MASTER: 该节点是主节点
  • REDISMODULE_NODE_SLAVE: 该节点是一个副本
  • REDISMODULE_NODE_PFAIL: 我们将该节点视为失败
  • REDISMODULE_NODE_FAIL: 集群同意该节点正在失效
  • REDISMODULE_NODE_NOFAILOVER: 从节点配置为永不进行故障转移

RedisModule_SetClusterFlags

void RedisModule_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags);

自版本起可用: 5.0.0

设置Redis集群标志以改变Redis集群的正常行为,特别是为了禁用某些功能。这对于使用集群API创建不同分布式系统但仍希望使用Redis集群消息总线的模块非常有用。可以设置的标志:

  • CLUSTER_MODULE_FLAG_NO_FAILOVER
  • CLUSTER_MODULE_FLAG_NO_REDIRECTION

具有以下效果:

  • NO_FAILOVER: 防止Redis Cluster的从节点在主机死亡时进行故障转移。 同时禁用副本迁移功能。

  • NO_REDIRECTION: 每个节点都会接受任何键,而不会尝试根据Redis集群算法进行分区。槽信息仍然会在集群中传播,但不会产生效果。

RedisModule_ClusterKeySlot

unsigned int RedisModule_ClusterKeySlot(RedisModuleString *key);

自版本起可用: 7.4.0

返回一个键的集群槽,类似于CLUSTER KEYSLOT命令。 即使未启用集群模式,此函数仍然有效。

RedisModule_ClusterCanonicalKeyNameInSlot

const char *RedisModule_ClusterCanonicalKeyNameInSlot(unsigned int slot);

自版本起可用: 7.4.0

返回一个可以用作键或键中哈希标签的短字符串,使得该键映射到给定的集群槽。如果槽不是有效的槽,则返回NULL。

模块计时器 API

模块计时器是一种高精度的“绿色计时器”抽象,每个模块都可以毫无问题地注册数百万个计时器,即使实际的事件循环只有一个计时器,该计时器用于唤醒模块计时器子系统以处理下一个事件。

所有的计时器都存储在一个基数树中,按过期时间排序,当主Redis事件循环计时器回调被调用时,我们尝试逐个处理所有已经过期的计时器。然后我们重新进入事件循环,注册一个计时器,该计时器将在下一个要处理的模块计时器过期时过期。

每当活动计时器列表降至零时,我们取消注册主事件循环计时器,以便在不使用此功能时没有开销。

RedisModule_CreateTimer

RedisModuleTimerID RedisModule_CreateTimer(RedisModuleCtx *ctx,
                                           mstime_t period,
                                           RedisModuleTimerProc callback,
                                           void *data);

自版本起可用: 5.0.0

创建一个新的计时器,它将在period毫秒后触发,并使用data作为参数调用指定的函数。返回的计时器ID可用于从计时器获取信息或在触发前停止它。 请注意,对于重复计时器的常见用例(在RedisModuleTimerProc回调中重新注册计时器),调用此API的时间很重要: 如果在'callback'开始时调用,意味着事件将每隔'period'触发一次。 如果在'callback'结束时调用,意味着事件之间将有'period'毫秒的间隔。 (如果执行'callback'所需的时间可以忽略不计,上述两种说法意思相同)

RedisModule_StopTimer

int RedisModule_StopTimer(RedisModuleCtx *ctx,
                          RedisModuleTimerID id,
                          void **data);

自版本起可用: 5.0.0

停止一个计时器,如果找到计时器,属于调用模块,并且已停止,则返回REDISMODULE_OK,否则返回REDISMODULE_ERR。如果数据指针不为NULL,则将其设置为创建计时器时数据参数的值。

RedisModule_GetTimerInfo

int RedisModule_GetTimerInfo(RedisModuleCtx *ctx,
                             RedisModuleTimerID id,
                             uint64_t *remaining,
                             void **data);

自版本起可用: 5.0.0

获取定时器的信息:它在触发前的剩余时间(以毫秒为单位),以及与定时器关联的私有数据指针。如果指定的定时器不存在或属于不同的模块,则不返回任何信息,函数返回REDISMODULE_ERR,否则返回REDISMODULE_OK。如果调用者不需要某些信息,参数remaining或data可以为NULL。

模块事件循环 API

RedisModule_EventLoopAdd

int RedisModule_EventLoopAdd(int fd,
                             int mask,
                             RedisModuleEventLoopFunc func,
                             void *user_data);

自版本起可用: 7.0.0

向事件循环添加一个管道/套接字事件。

  • mask 必须是以下值之一:

    • REDISMODULE_EVENTLOOP_READABLE
    • REDISMODULE_EVENTLOOP_WRITABLE
    • REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE

成功时返回REDISMODULE_OK,否则返回REDISMODULE_ERR并将errno设置为以下值:

  • ERANGE: fd 是负数或高于 Redis 配置中的 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);
}
RedisModule_EventLoopAdd(fd, REDISMODULE_EVENTLOOP_READABLE, onReadable, NULL);

RedisModule_EventLoopDel

int RedisModule_EventLoopDel(int fd, int mask);

自版本起可用: 7.0.0

从事件循环中删除一个管道/套接字事件。

  • mask 必须是以下值之一:

    • REDISMODULE_EVENTLOOP_READABLE
    • REDISMODULE_EVENTLOOP_WRITABLE
    • REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE

成功时返回REDISMODULE_OK,否则返回REDISMODULE_ERR并将errno设置为以下值:

  • ERANGE: fd 是负数或高于 Redis 配置中的 maxclients
  • EINVAL: mask 值无效。

RedisModule_EventLoopAddOneShot

int RedisModule_EventLoopAddOneShot(RedisModuleEventLoopOneShotFunc func,
                                    void *user_data);

自版本起可用: 7.0.0

此函数可以从其他线程调用,以在Redis主线程上触发回调。成功时返回REDISMODULE_OK。如果func为NULL,则返回REDISMODULE_ERR并将errno设置为EINVAL。

模块 ACL API

在Redis中实现了一个用于认证和授权的钩子。

RedisModule_CreateModuleUser

RedisModuleUser *RedisModule_CreateModuleUser(const char *name);

自版本起可用: 6.0.0

创建一个Redis ACL用户,模块可以使用该用户来验证客户端。 获取用户后,模块应使用RedisModule_SetUserACL()函数设置该用户可以执行的操作。 一旦配置完成,可以使用RedisModule_AuthClientWithUser()函数,使用指定的ACL规则来验证连接。

请注意:

  • 在此创建的用户不会在ACL命令中列出。
  • 在这里创建的用户不会检查名称是否重复,因此需要调用此函数的模块来确保不会创建具有相同名称的用户。
  • 创建的用户可用于验证多个Redis连接。

调用者稍后可以使用函数 RedisModule_FreeModuleUser()来释放用户。当调用此函数时,如果仍有客户端使用此用户进行身份验证,它们将被断开连接。 释放用户的函数应仅在调用者确实希望使该用户无效以定义具有不同功能的新用户时使用。

RedisModule_FreeModuleUser

int RedisModule_FreeModuleUser(RedisModuleUser *user);

自版本起可用: 6.0.0

释放给定的用户并断开所有已通过其认证的客户端连接。有关详细用法,请参见RedisModule_CreateModuleUser

RedisModule_SetModuleUserACL

int RedisModule_SetModuleUserACL(RedisModuleUser *user, const char* acl);

自版本起可用: 6.0.0

设置通过Redis模块接口创建的用户权限。语法与ACL SETUSER相同,因此请参阅acl.c中的文档以获取更多信息。有关详细用法,请参见RedisModule_CreateModuleUser

成功时返回REDISMODULE_OK,失败时返回REDISMODULE_ERR,并会设置一个errno来描述操作失败的原因。

RedisModule_SetModuleUserACLString

int RedisModule_SetModuleUserACLString(RedisModuleCtx *ctx,
                                       RedisModuleUser *user,
                                       const char *acl,
                                       RedisModuleString **error);

自版本起可用: 7.0.6

设置用户的权限,使用完整的ACL字符串,例如在redis ACL SETUSER命令行API中使用的字符串。这与RedisModule_SetModuleUserACL不同,后者一次只能接受单个ACL操作。

成功时返回REDISMODULE_OK,失败时返回REDISMODULE_ERR 如果错误地提供了RedisModuleString,将返回描述错误的字符串

RedisModule_GetModuleUserACLString

RedisModuleString *RedisModule_GetModuleUserACLString(RedisModuleUser *user);

自版本起可用: 7.0.6

获取给定用户的ACL字符串 返回一个RedisModuleString

RedisModule_GetCurrentUserName

RedisModuleString *RedisModule_GetCurrentUserName(RedisModuleCtx *ctx);

自版本起可用: 7.0.0

检索当前上下文背后的客户端连接的用户名。 该用户名可以稍后用于获取RedisModuleUser。 更多信息请参见RedisModule_GetModuleUserFromUserName

返回的字符串必须通过RedisModule_FreeString()释放,或者通过启用自动内存管理来释放。

RedisModule_GetModuleUserFromUserName

RedisModuleUser *RedisModule_GetModuleUserFromUserName(RedisModuleString *name);

自版本起可用: 7.0.0

一个RedisModuleUser可以用来检查命令、键或频道是否可以根据与该用户关联的ACL规则执行或访问。 当一个模块想要对一般的ACL用户(不是由RedisModule_CreateModuleUser创建的)进行ACL检查时,它可以通过此API获取RedisModuleUser,基于通过RedisModule_GetCurrentUserName检索到的用户名。

由于普通ACL用户可以随时被删除,因此RedisModuleUser应仅在调用此函数的上下文中使用。为了在该上下文之外进行ACL检查,模块可以存储用户名,并在任何其他上下文中调用此API。

如果用户被禁用或用户不存在,则返回NULL。 调用者应稍后使用函数RedisModule_FreeModuleUser()释放用户。

RedisModule_ACLCheckCommandPermissions

int RedisModule_ACLCheckCommandPermissions(RedisModuleUser *user,
                                           RedisModuleString **argv,
                                           int argc);

自版本起可用: 7.0.0

检查命令是否可以根据与之关联的ACL由用户执行。

成功时返回REDISMODULE_OK,否则返回REDISMODULE_ERR,并将errno设置为以下值:

  • ENOENT: 指定的命令不存在。
  • EACCES: 根据ACL规则,无法执行命令

RedisModule_ACLCheckKeyPermissions

int RedisModule_ACLCheckKeyPermissions(RedisModuleUser *user,
                                       RedisModuleString *key,
                                       int flags);

自版本起可用: 7.0.0

根据附加到用户的ACL和表示密钥访问的标志,检查用户是否可以访问该密钥。这些标志与逻辑操作中使用的标志相同。这些标志在RedisModule_SetCommandInfo中记录为REDISMODULE_CMD_KEY_ACCESSREDISMODULE_CMD_KEY_UPDATEREDISMODULE_CMD_KEY_INSERTREDISMODULE_CMD_KEY_DELETE标志。

如果没有提供任何标志,用户仍然需要拥有对密钥的某些访问权限,此命令才能成功返回。

如果用户能够访问密钥,则返回REDISMODULE_OK,否则返回REDISMODULE_ERR,并将errno设置为以下值之一:

  • EINVAL: 提供的标志无效。
  • EACCESS: 用户没有权限访问该密钥。

RedisModule_ACLCheckChannelPermissions

int RedisModule_ACLCheckChannelPermissions(RedisModuleUser *user,
                                           RedisModuleString *ch,
                                           int flags);

自版本起可用: 7.0.0

检查用户是否可以根据给定的访问标志访问pubsub频道。有关可以传入的可能标志的更多信息,请参见RedisModule_ChannelAtPosWithFlags

如果用户能够访问pubsub频道,则返回REDISMODULE_OK,否则返回REDISMODULE_ERR,并将errno设置为以下值之一:

  • EINVAL: 提供的标志无效。
  • EACCESS: 用户没有权限访问pubsub频道。

RedisModule_ACLAddLogEntry

int RedisModule_ACLAddLogEntry(RedisModuleCtx *ctx,
                               RedisModuleUser *user,
                               RedisModuleString *object,
                               RedisModuleACLLogEntryReason reason);

自版本起可用: 7.0.0

在ACL日志中添加一个新条目。 成功时返回REDISMODULE_OK,错误时返回REDISMODULE_ERR

有关ACL日志的更多信息,请参考https://redis.io/commands/acl-log

RedisModule_ACLAddLogEntryByUserName

int RedisModule_ACLAddLogEntryByUserName(RedisModuleCtx *ctx,
                                         RedisModuleString *username,
                                         RedisModuleString *object,
                                         RedisModuleACLLogEntryReason reason);

自版本起可用: 7.2.0

使用提供的username RedisModuleString在ACL日志中添加一个新条目。 成功时返回REDISMODULE_OK,错误时返回REDISMODULE_ERR

有关ACL日志的更多信息,请参考https://redis.io/commands/acl-log

RedisModule_AuthenticateClientWithUser

int RedisModule_AuthenticateClientWithUser(RedisModuleCtx *ctx,
                                           RedisModuleUser *module_user,
                                           RedisModuleUserChangedFunc callback,
                                           void *privdata,
                                           uint64_t *client_id);

自版本起可用: 6.0.0

使用提供的 Redis ACL 用户对当前上下文的用户进行身份验证。 如果用户被禁用,则返回 REDISMODULE_ERR

有关回调的信息,请参阅authenticateClientWithUser,client_id,以及认证的一般用法。

RedisModule_AuthenticateClientWithACLUser

int RedisModule_AuthenticateClientWithACLUser(RedisModuleCtx *ctx,
                                              const char *name,
                                              size_t len,
                                              RedisModuleUserChangedFunc callback,
                                              void *privdata,
                                              uint64_t *client_id);

自版本起可用: 6.0.0

使用提供的Redis ACL用户对当前上下文的用户进行身份验证。 如果用户被禁用或用户不存在,则返回REDISMODULE_ERR

有关回调、client_id以及身份验证的一般用法的信息,请参见authenticateClientWithUser。

RedisModule_DeauthenticateAndCloseClient

int RedisModule_DeauthenticateAndCloseClient(RedisModuleCtx *ctx,
                                             uint64_t client_id);

自版本起可用: 6.0.0

取消认证并关闭客户端。客户端资源不会立即释放,但会在后台作业中清理。这是推荐的取消客户端认证的方式,因为大多数客户端无法处理用户被取消认证的情况。当客户端不存在时返回REDISMODULE_ERR,当操作成功时返回REDISMODULE_OK

客户端ID是从RedisModule_AuthenticateClientWithUserRedisModule_AuthenticateClientWithACLUser API返回的,但也可以通过 CLIENT API或服务器事件获取。

此函数不是线程安全的,必须在命令或线程安全上下文的上下文中执行。

RedisModule_RedactClientCommandArgument

int RedisModule_RedactClientCommandArgument(RedisModuleCtx *ctx, int pos);

自版本起可用: 7.0.0

对指定位置上的客户端命令参数进行编辑。编辑后的参数在面向用户的命令(如SLOWLOG或MONITOR)中会被模糊处理,并且永远不会写入服务器日志。此命令可以在同一位置上多次调用。

请注意,命令名称,位置0,不能被编辑。

如果参数被编辑,则返回REDISMODULE_OK;如果传入的参数无效或位置超出客户端参数范围,则返回REDISMODULE_ERR

RedisModule_GetClientCertificate

RedisModuleString *RedisModule_GetClientCertificate(RedisModuleCtx *ctx,
                                                    uint64_t client_id);

自以下版本可用: 6.0.9

返回客户端用于验证此连接的X.509客户端证书。

返回值是一个分配的RedisModuleString,它是一个以PEM(Base64)格式编码的X.509证书。它应该由调用者释放(或自动释放)。

在以下情况下返回NULL值:

  • 连接ID不存在
  • 连接不是TLS连接
  • 连接是一个TLS连接,但未使用客户端证书

模块字典 API

实现了一个排序字典(实际上由基数树支持),具有常见的获取/设置/删除/项目数量API,以及一个能够前后移动的迭代器。

RedisModule_CreateDict

RedisModuleDict *RedisModule_CreateDict(RedisModuleCtx *ctx);

自版本起可用: 5.0.0

创建一个新的字典。'ctx'指针可以是当前模块上下文或NULL,具体取决于您的需求。请遵循以下规则:

  1. 如果您计划保留对此字典的引用,并且该引用将在创建它的模块回调时间之后仍然存在,请使用NULL上下文。
  2. 如果在创建字典时没有可用的上下文,请使用NULL上下文(当然...)。
  3. 然而,如果字典的生存时间仅限于回调范围,则使用当前回调上下文作为'ctx'参数。在这种情况下,如果启用,您可以享受自动内存管理,它将回收字典内存,以及由Next / Prev字典迭代器调用返回的字符串。

RedisModule_FreeDict

void RedisModule_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d);

自版本起可用: 5.0.0

释放一个使用RedisModule_CreateDict()创建的字典。只有在字典是使用上下文而不是传递NULL创建的情况下,才需要传递上下文指针'ctx'。

RedisModule_DictSize

uint64_t RedisModule_DictSize(RedisModuleDict *d);

自版本起可用: 5.0.0

返回字典的大小(键的数量)。

RedisModule_DictSetC

int RedisModule_DictSetC(RedisModuleDict *d,
                         void *key,
                         size_t keylen,
                         void *ptr);

自版本起可用: 5.0.0

将指定的键存储到字典中,将其值设置为指针'ptr'。如果键成功添加,因为它之前不存在,则返回REDISMODULE_OK。否则,如果键已经存在,函数返回REDISMODULE_ERR

RedisModule_DictReplaceC

int RedisModule_DictReplaceC(RedisModuleDict *d,
                             void *key,
                             size_t keylen,
                             void *ptr);

自版本起可用: 5.0.0

类似于 RedisModule_DictSetC(),但如果键已经存在,则会用新值替换该键。

RedisModule_DictSet

int RedisModule_DictSet(RedisModuleDict *d, RedisModuleString *key, void *ptr);

自版本起可用: 5.0.0

类似于 RedisModule_DictSetC(),但将键作为 RedisModuleString 传递。

RedisModule_DictReplace

int RedisModule_DictReplace(RedisModuleDict *d,
                            RedisModuleString *key,
                            void *ptr);

自版本起可用: 5.0.0

类似于 RedisModule_DictReplaceC(),但将键作为 RedisModuleString 传递。

RedisModule_DictGetC

void *RedisModule_DictGetC(RedisModuleDict *d,
                           void *key,
                           size_t keylen,
                           int *nokey);

自版本起可用: 5.0.0

返回存储在指定键的值。如果键不存在,或者你实际上在键中存储了NULL,函数将返回NULL。因此,可选地,如果'nokey'指针不为NULL,如果键不存在,它将被引用设置为1,如果键存在,则设置为0。

RedisModule_DictGet

void *RedisModule_DictGet(RedisModuleDict *d,
                          RedisModuleString *key,
                          int *nokey);

自版本起可用: 5.0.0

类似于 RedisModule_DictGetC(),但将键作为 RedisModuleString 传递。

RedisModule_DictDelC

int RedisModule_DictDelC(RedisModuleDict *d,
                         void *key,
                         size_t keylen,
                         void *oldval);

自版本起可用: 5.0.0

从字典中移除指定的键,如果找到并删除了键,则返回REDISMODULE_OK,如果字典中没有这样的键,则返回REDISMODULE_ERR。当操作成功时,如果'oldval'不为NULL,则'*oldval'被设置为删除前存储在键中的值。使用此功能可以在删除键之前获取指向值的指针(例如为了释放它),而无需在删除键之前调用RedisModule_DictGet()

RedisModule_DictDel

int RedisModule_DictDel(RedisModuleDict *d,
                        RedisModuleString *key,
                        void *oldval);

自版本起可用: 5.0.0

类似于 RedisModule_DictDelC(),但将键作为 RedisModuleString 获取。

RedisModule_DictIteratorStartC

RedisModuleDictIter *RedisModule_DictIteratorStartC(RedisModuleDict *d,
                                                    const char *op,
                                                    void *key,
                                                    size_t keylen);

自版本起可用: 5.0.0

返回一个迭代器,设置以便从指定的键开始迭代,通过应用操作符'op',它只是一个字符串,指定用于查找第一个元素的比较操作符。可用的操作符有:

  • ^ – 寻找第一个(字典序较小的)键。
  • $ – 查找最后一个(按字典顺序更大的)键。
  • > – 寻找第一个大于指定键的元素。
  • >= – 寻找第一个大于或等于指定键的元素。
  • < – 寻找第一个小于指定键的元素。
  • <= – 寻找第一个小于或等于指定键的元素。
  • == – 寻找与指定键完全匹配的第一个元素。

请注意,对于 ^$,传递的键不会被使用,用户可以只传递长度为 0 的 NULL。

如果无法根据传递的键和操作符找到开始迭代的元素,RedisModule_DictNext() / Prev() 将在第一次调用时返回 REDISMODULE_ERR,否则它们将生成元素。

RedisModule_DictIteratorStart

RedisModuleDictIter *RedisModule_DictIteratorStart(RedisModuleDict *d,
                                                   const char *op,
                                                   RedisModuleString *key);

自版本起可用: 5.0.0

RedisModule_DictIteratorStartC完全相同,但键作为RedisModuleString传递。

RedisModule_DictIteratorStop

void RedisModule_DictIteratorStop(RedisModuleDictIter *di);

自版本起可用: 5.0.0

释放由RedisModule_DictIteratorStart()创建的迭代器。此调用是必需的,否则模块中会引入内存泄漏。

RedisModule_DictIteratorReseekC

int RedisModule_DictIteratorReseekC(RedisModuleDictIter *di,
                                    const char *op,
                                    void *key,
                                    size_t keylen);

自版本起可用: 5.0.0

在使用RedisModule_DictIteratorStart()创建后,可以通过使用此API调用来更改迭代器当前选择的元素。基于操作符和键的结果与函数RedisModule_DictIteratorStart()完全相同,但在这种情况下,如果找到所寻找的元素,则返回值为REDISMODULE_OK,如果无法找到指定的元素,则返回REDISMODULE_ERR。可以根据需要多次重新寻找迭代器。

RedisModule_DictIteratorReseek

int RedisModule_DictIteratorReseek(RedisModuleDictIter *di,
                                   const char *op,
                                   RedisModuleString *key);

自版本起可用: 5.0.0

类似于 RedisModule_DictIteratorReseekC(),但将键作为 RedisModuleString 传递。

RedisModule_DictNextC

void *RedisModule_DictNextC(RedisModuleDictIter *di,
                            size_t *keylen,
                            void **dataptr);

自版本起可用: 5.0.0

返回字典迭代器 di 的当前项并移动到下一个元素。如果迭代器已经产生了最后一个元素并且没有其他元素可返回,则返回 NULL,否则返回指向表示键的字符串的指针,并通过引用设置 *keylen 的长度(如果 keylen 不为 NULL)。如果 *dataptr 不为 NULL,则将其设置为存储在返回键中的指针的值作为辅助数据(由 RedisModule_DictSet API 设置)。

使用示例:

 ... create the iterator here ...
 char *key;
 void *data;
 while((key = RedisModule_DictNextC(iter,&keylen,&data)) != NULL) {
     printf("%.*s %p\n", (int)keylen, key, data);
 }

返回的指针类型为void,因为有时根据其包含或不包含二进制数据的情况,将其转换为char*unsigned char*是有意义的,因此这个API最终使用起来更加方便。

返回的指针的有效性直到下一次调用next/prev迭代器步骤为止。此外,一旦迭代器被释放,指针将不再有效。

RedisModule_DictPrevC

void *RedisModule_DictPrevC(RedisModuleDictIter *di,
                            size_t *keylen,
                            void **dataptr);

自版本起可用: 5.0.0

此函数与RedisModule_DictNext()完全相同,但在返回迭代器中当前选定的元素后,它会选择前一个元素(按字典顺序较小)而不是下一个元素。

RedisModule_DictNext

RedisModuleString *RedisModule_DictNext(RedisModuleCtx *ctx,
                                        RedisModuleDictIter *di,
                                        void **dataptr);

自版本起可用: 5.0.0

类似于 RedisModuleNextC(),但它不是返回一个内部分配的缓冲区和键长度,而是直接返回在指定上下文 'ctx' 中分配的模块字符串对象(该上下文可能为 NULL,就像主 API RedisModule_CreateString 一样)。

返回的字符串对象在使用后应被释放,无论是手动释放还是通过使用具有自动内存管理的上下文。

RedisModule_DictPrev

RedisModuleString *RedisModule_DictPrev(RedisModuleCtx *ctx,
                                        RedisModuleDictIter *di,
                                        void **dataptr);

自版本起可用: 5.0.0

类似于 RedisModule_DictNext(),但在返回迭代器中当前选中的元素后,它会选择前一个元素(按字典序较小)而不是下一个元素。

RedisModule_DictCompareC

int RedisModule_DictCompareC(RedisModuleDictIter *di,
                             const char *op,
                             void *key,
                             size_t keylen);

自版本起可用: 5.0.0

根据操作符 'op'(有效的操作符集与RedisModule_DictIteratorStart相同),将迭代器当前指向的元素与由key/keylen指定的元素进行比较。如果比较成功,命令返回REDISMODULE_OK,否则返回REDISMODULE_ERR

当我们只想发出一个字典序范围时,这很有用,因此在循环中,当我们迭代元素时,我们还可以检查我们是否仍在范围内。

如果迭代器达到元素结束条件,函数返回 REDISMODULE_ERR

RedisModule_DictCompare

int RedisModule_DictCompare(RedisModuleDictIter *di,
                            const char *op,
                            RedisModuleString *key);

自版本起可用: 5.0.0

类似于 RedisModule_DictCompareC,但获取要与当前迭代器键进行比较的键作为 RedisModuleString

模块信息字段

RedisModule_InfoAddSection

int RedisModule_InfoAddSection(RedisModuleInfoCtx *ctx, const char *name);

自版本起可用: 6.0.0

用于在添加任何字段之前开始一个新部分。部分名称将以_为前缀,并且只能包含A-Z、a-z、0-9。NULL或空字符串表示使用默认部分(仅)。当返回值为REDISMODULE_ERR时,应跳过该部分。

RedisModule_InfoBeginDictField

int RedisModule_InfoBeginDictField(RedisModuleInfoCtx *ctx, const char *name);

自版本起可用: 6.0.0

开始一个字典字段,类似于INFO KEYSPACE中的字段。使用普通的 RedisModule_InfoAddField* 函数将项目添加到此字段,并以 RedisModule_InfoEndDictField结束。

RedisModule_InfoEndDictField

int RedisModule_InfoEndDictField(RedisModuleInfoCtx *ctx);

自版本起可用: 6.0.0

结束一个字典字段,参见 RedisModule_InfoBeginDictField

RedisModule_InfoAddFieldString

int RedisModule_InfoAddFieldString(RedisModuleInfoCtx *ctx,
                                   const char *field,
                                   RedisModuleString *value);

自版本起可用: 6.0.0

RedisModuleInfoFunc使用来添加信息字段。 每个字段将自动以_为前缀。 字段名称或值不得包含\r\n:

RedisModule_InfoAddFieldCString

int RedisModule_InfoAddFieldCString(RedisModuleInfoCtx *ctx,
                                    const char *field,
                                    const char *value);

自版本起可用: 6.0.0

参见 RedisModule_InfoAddFieldString().

RedisModule_InfoAddFieldDouble

int RedisModule_InfoAddFieldDouble(RedisModuleInfoCtx *ctx,
                                   const char *field,
                                   double value);

自版本起可用: 6.0.0

参见 RedisModule_InfoAddFieldString()

RedisModule_InfoAddFieldLongLong

int RedisModule_InfoAddFieldLongLong(RedisModuleInfoCtx *ctx,
                                     const char *field,
                                     long long value);

自版本起可用: 6.0.0

参见 RedisModule_InfoAddFieldString()

RedisModule_InfoAddFieldULongLong

int RedisModule_InfoAddFieldULongLong(RedisModuleInfoCtx *ctx,
                                      const char *field,
                                      unsigned long long value);

自版本起可用: 6.0.0

参见 RedisModule_InfoAddFieldString()

RedisModule_RegisterInfoFunc

int RedisModule_RegisterInfoFunc(RedisModuleCtx *ctx, RedisModuleInfoFunc cb);

自版本起可用: 6.0.0

为INFO命令注册回调。回调应通过调用RedisModule_InfoAddField*()函数来添加INFO字段。

RedisModule_GetServerInfo

RedisModuleServerInfoData *RedisModule_GetServerInfo(RedisModuleCtx *ctx,
                                                     const char *section);

自版本起可用: 6.0.0

获取与INFO命令返回的服务器信息类似的信息。此函数接受一个可选的'section'参数,该参数可能为NULL。返回值包含输出,并可以与RedisModule_ServerInfoGetField等一起使用以获取各个字段。完成后,需要使用RedisModule_FreeServerInfo或启用自动内存管理机制来释放它。

RedisModule_FreeServerInfo

void RedisModule_FreeServerInfo(RedisModuleCtx *ctx,
                                RedisModuleServerInfoData *data);

自版本起可用: 6.0.0

使用RedisModule_GetServerInfo()创建的自由数据。只有在字典是使用上下文创建而不是传递NULL时,才需要传递上下文指针'ctx'。

RedisModule_ServerInfoGetField

RedisModuleString *RedisModule_ServerInfoGetField(RedisModuleCtx *ctx,
                                                  RedisModuleServerInfoData *data,
                                                  const char* field);

自版本起可用: 6.0.0

从使用RedisModule_GetServerInfo()收集的数据中获取字段的值。如果您想使用自动内存机制来释放返回的字符串,则需要传递上下文指针'ctx'。如果未找到该字段,则返回值为NULL。

RedisModule_ServerInfoGetFieldC

const char *RedisModule_ServerInfoGetFieldC(RedisModuleServerInfoData *data,
                                            const char* field);

自版本起可用: 6.0.0

类似于RedisModule_ServerInfoGetField,但返回一个不应由调用者释放的char*。

RedisModule_ServerInfoGetFieldSigned

long long RedisModule_ServerInfoGetFieldSigned(RedisModuleServerInfoData *data,
                                               const char* field,
                                               int *out_err);

自版本起可用: 6.0.0

从使用RedisModule_GetServerInfo()收集的数据中获取字段的值。如果未找到该字段,或者该字段不是数值或超出范围,则返回值为0,并且可选的out_err参数将被设置为REDISMODULE_ERR

RedisModule_ServerInfoGetFieldUnsigned

unsigned long long RedisModule_ServerInfoGetFieldUnsigned(RedisModuleServerInfoData *data,
                                                          const char* field,
                                                          int *out_err);

自版本起可用: 6.0.0

从使用RedisModule_GetServerInfo()收集的数据中获取字段的值。如果未找到该字段,或者该字段不是数值或超出范围,则返回值为0,并且可选的out_err参数将被设置为REDISMODULE_ERR

RedisModule_ServerInfoGetFieldDouble

double RedisModule_ServerInfoGetFieldDouble(RedisModuleServerInfoData *data,
                                            const char* field,
                                            int *out_err);

自版本起可用: 6.0.0

从使用RedisModule_GetServerInfo()收集的数据中获取字段的值。如果未找到该字段,或者该字段不是双精度类型,则返回值为0,并且可选的out_err参数将被设置为REDISMODULE_ERR

模块实用工具API

RedisModule_GetRandomBytes

void RedisModule_GetRandomBytes(unsigned char *dst, size_t len);

自版本起可用: 5.0.0

使用SHA1在计数器模式下返回随机字节,并使用/dev/urandom初始化的种子。此函数速度很快,因此可以用于生成大量字节,而不会对操作系统熵池产生任何影响。目前此函数不是线程安全的。

RedisModule_GetRandomHexChars

void RedisModule_GetRandomHexChars(char *dst, size_t len);

自版本起可用: 5.0.0

类似于 RedisModule_GetRandomBytes(),但不是将字符串设置为随机字节,而是将字符串设置为十六进制字符集 [0-9a-f] 中的随机字符。

模块 API 导出 / 导入

RedisModule_ExportSharedAPI

int RedisModule_ExportSharedAPI(RedisModuleCtx *ctx,
                                const char *apiname,
                                void *func);

自以下版本可用: 5.0.4

此函数由模块调用,以便导出具有给定名称的某些API。其他模块将能够通过调用对称函数RedisModule_GetSharedAPI()并将返回值转换为正确的函数指针来使用此API。

如果名称未被占用,函数将返回REDISMODULE_OK, 否则将返回REDISMODULE_ERR并且不会执行任何操作。

重要提示:apiname 参数应该是一个具有静态生命周期的字符串字面量。API 依赖于它将来始终有效的这一事实。

RedisModule_GetSharedAPI

void *RedisModule_GetSharedAPI(RedisModuleCtx *ctx, const char *apiname);

自以下版本可用: 5.0.4

请求一个导出的API指针。返回值只是一个void指针,调用此函数的人需要将其转换为正确的函数指针,因此这是模块之间的私有约定。

如果请求的API不可用,则返回NULL。由于模块可以在不同的时间以不同的顺序加载,因此这些函数调用应放在某些模块通用API注册步骤中,该步骤在每次模块尝试执行需要外部API的命令时调用:如果某些API无法解析,命令应返回错误。

这是一个示例:

int ... myCommandImplementation(void) {
   if (getExternalAPIs() == 0) {
        reply with an error here if we cannot have the APIs
   }
   // Use the API:
   myFunctionPointer(foo);
}

函数 registerAPI() 是:

int getExternalAPIs(void) {
    static int api_loaded = 0;
    if (api_loaded != 0) return 1; // APIs already resolved.

    myFunctionPointer = RedisModule_GetSharedAPI("...");
    if (myFunctionPointer == NULL) return 0;

    return 1;
}

模块命令过滤器 API

RedisModule_RegisterCommandFilter

RedisModuleCommandFilter *RedisModule_RegisterCommandFilter(RedisModuleCtx *ctx,
                                                            RedisModuleCommandFilterFunc callback,
                                                            int flags);

自以下版本可用: 5.0.5

注册一个新的命令过滤器函数。

命令过滤使得模块可以通过插入到所有命令的执行流程中来扩展Redis。

注册的过滤器在Redis执行任何命令之前被调用。这包括核心Redis命令和任何模块注册的命令。过滤器适用于所有执行路径,包括:

  1. 由客户端调用。
  2. 通过任何模块的RedisModule_Call()调用。
  3. 通过Lua调用 redis.call()
  4. 从主节点复制命令。

过滤器在一个特殊的过滤器上下文中执行,这与RedisModuleCtx不同且更为有限。因为过滤器影响任何命令,所以必须以非常高效的方式实现,以减少对Redis性能的影响。所有需要有效上下文的Redis模块API调用(例如RedisModule_Call()RedisModule_OpenKey()等)在过滤器上下文中都不受支持。

RedisModuleCommandFilterCtx 可用于检查或修改执行的命令及其参数。由于过滤器在 Redis 开始处理命令之前执行,任何更改都会影响命令的处理方式。例如,模块可以通过这种方式覆盖 Redis 命令:

  1. 注册一个MODULE.SET命令,该命令实现了Redis SET命令的扩展版本。
  2. 注册一个命令过滤器,用于检测在特定键模式上调用SET的情况。一旦检测到,过滤器将把SET的第一个参数替换为MODULE.SET
  3. 当过滤器执行完成后,Redis 会考虑新的命令名称,因此执行模块自己的命令。

请注意,在上述用例中,如果MODULE.SET本身使用了 RedisModule_Call(),过滤器也将应用于该调用。如果 不希望这样,可以在注册过滤器时设置REDISMODULE_CMDFILTER_NOSELF标志。

REDISMODULE_CMDFILTER_NOSELF 标志阻止源自模块自身的 RedisModule_Call() 的执行流到达过滤器。只要执行从模块的命令上下文或与阻塞命令相关联的线程安全上下文开始,该标志对所有执行流(包括嵌套的执行流)都有效。

分离的线程安全上下文与模块关联,因此无法通过此标志进行保护。

如果注册了多个过滤器(由相同或不同的模块注册),它们将按照注册的顺序执行。

RedisModule_UnregisterCommandFilter

int RedisModule_UnregisterCommandFilter(RedisModuleCtx *ctx,
                                        RedisModuleCommandFilter *filter);

自以下版本可用: 5.0.5

注销一个命令过滤器。

RedisModule_CommandFilterArgsCount

int RedisModule_CommandFilterArgsCount(RedisModuleCommandFilterCtx *fctx);

自以下版本可用: 5.0.5

返回过滤命令的参数数量。参数数量包括命令本身。

RedisModule_CommandFilterArgGet

RedisModuleString *RedisModule_CommandFilterArgGet(RedisModuleCommandFilterCtx *fctx,
                                                   int pos);

自以下版本可用: 5.0.5

返回指定的命令参数。第一个参数(位置0)是命令本身,其余的是用户提供的参数。

RedisModule_CommandFilterArgInsert

int RedisModule_CommandFilterArgInsert(RedisModuleCommandFilterCtx *fctx,
                                       int pos,
                                       RedisModuleString *arg);

自以下版本可用: 5.0.5

通过在指定位置插入一个新参数来修改过滤后的命令。指定的RedisModuleString参数可能在过滤器上下文销毁后被Redis使用,因此它不能是自动内存分配的、释放的或在其他地方使用的。

RedisModule_CommandFilterArgReplace

int RedisModule_CommandFilterArgReplace(RedisModuleCommandFilterCtx *fctx,
                                        int pos,
                                        RedisModuleString *arg);

自以下版本可用: 5.0.5

通过用新参数替换现有参数来修改过滤后的命令。 指定的RedisModuleString参数可能在过滤器上下文销毁后被Redis使用,因此它不能是自动内存分配的、释放的或在其他地方使用的。

RedisModule_CommandFilterArgDelete

int RedisModule_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx,
                                       int pos);

自以下版本可用: 5.0.5

通过删除指定位置的参数来修改过滤后的命令。

RedisModule_CommandFilterGetClientId

unsigned long long RedisModule_CommandFilterGetClientId(RedisModuleCommandFilterCtx *fctx);

自版本起可用: 7.2.0

获取发出我们正在过滤的命令的客户端的客户端ID

RedisModule_MallocSize

size_t RedisModule_MallocSize(void* ptr);

自版本起可用: 6.0.0

对于通过RedisModule_Alloc()RedisModule_Realloc()分配的给定指针,返回为其分配的内存量。请注意,这可能与我们通过分配调用分配的内存不同(更大),因为有时底层分配器会分配更多的内存。

RedisModule_MallocUsableSize

size_t RedisModule_MallocUsableSize(void *ptr);

自版本起可用: 7.0.1

类似于RedisModule_MallocSize,不同之处在于RedisModule_MallocUsableSize返回模块可用的内存大小。

RedisModule_MallocSizeString

size_t RedisModule_MallocSizeString(RedisModuleString* str);

自版本起可用: 7.0.0

RedisModule_MallocSize相同,只是它适用于RedisModuleString指针。

RedisModule_MallocSizeDict

size_t RedisModule_MallocSizeDict(RedisModuleDict* dict);

自版本起可用: 7.0.0

RedisModule_MallocSize相同,但它适用于RedisModuleDict指针。 请注意,返回的值仅是底层结构的开销, 它不包括键和值的分配大小。

RedisModule_GetUsedMemoryRatio

float RedisModule_GetUsedMemoryRatio(void);

自版本起可用: 6.0.0

返回一个介于0到1之间的数字,表示当前使用的内存量相对于Redis的"maxmemory"配置的比例。

  • 0 - 未配置内存限制。
  • 介于0和1之间 - 内存使用百分比在0-1范围内归一化。
  • 恰好1 - 达到内存限制。
  • 大于1 - 使用的内存超过了配置的限制。

扫描键空间和哈希

RedisModule_ScanCursorCreate

RedisModuleScanCursor *RedisModule_ScanCursorCreate(void);

自版本起可用: 6.0.0

创建一个新的游标,用于与RedisModule_Scan一起使用

RedisModule_ScanCursorRestart

void RedisModule_ScanCursorRestart(RedisModuleScanCursor *cursor);

自版本起可用: 6.0.0

重新启动现有的游标。键将被重新扫描。

RedisModule_ScanCursorDestroy

void RedisModule_ScanCursorDestroy(RedisModuleScanCursor *cursor);

自版本起可用: 6.0.0

销毁光标结构。

RedisModule_Scan

int RedisModule_Scan(RedisModuleCtx *ctx,
                     RedisModuleScanCursor *cursor,
                     RedisModuleScanCB fn,
                     void *privdata);

自版本起可用: 6.0.0

扫描API,允许模块扫描所选数据库中的所有键和值。

扫描实现的回调。

void scan_callback(RedisModuleCtx *ctx, RedisModuleString *keyname,
                   RedisModuleKey *key, void *privdata);
  • ctx: 提供给扫描的redis模块上下文。
  • keyname: 由调用者拥有,如果在此函数之后使用,则需要保留。
  • key: 保存有关键和值的信息,它是尽力提供的,在某些情况下可能为NULL,在这种情况下,用户应该(可以)使用RedisModule_OpenKey()(以及CloseKey)。当它被提供时,它由调用者拥有,并在回调返回时释放。
  • privdata: 提供给RedisModule_Scan()的用户数据。

应该使用的方式:

 RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
 while(RedisModule_Scan(ctx, c, callback, privateData));
 RedisModule_ScanCursorDestroy(c);

也可以在实际调用RedisModule_Scan期间获取锁时,从另一个线程使用此API:

 RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
 RedisModule_ThreadSafeContextLock(ctx);
 while(RedisModule_Scan(ctx, c, callback, privateData)){
     RedisModule_ThreadSafeContextUnlock(ctx);
     // do some background job
     RedisModule_ThreadSafeContextLock(ctx);
 }
 RedisModule_ScanCursorDestroy(c);

如果还有更多元素要扫描,函数将返回1,否则返回0,如果调用失败,可能会设置errno。

也可以使用RedisModule_ScanCursorRestart重新启动现有的游标。

重要提示:从提供的保证角度来看,此API与Redis SCAN命令非常相似。这意味着API可能会报告重复的键,但保证在扫描过程从开始到结束期间至少报告一次每个键。

注意:如果您在回调中进行数据库更改,您应该意识到数据库的内部状态可能会发生变化。例如,删除或修改当前键是安全的,但删除任何其他键可能不安全。 此外,在迭代过程中操作Redis键空间可能会导致返回更多的重复项。一个安全的模式是将您想要修改的键名存储在其他地方,并在迭代完成后对这些键执行操作。然而,这可能会消耗大量内存,因此在迭代期间尽可能对当前键进行操作可能更有意义,因为这是安全的。

RedisModule_ScanKey

int RedisModule_ScanKey(RedisModuleKey *key,
                        RedisModuleScanCursor *cursor,
                        RedisModuleScanKeyCB fn,
                        void *privdata);

自版本起可用: 6.0.0

允许模块扫描哈希、集合或有序集合键中元素的扫描API

扫描实现的回调。

void scan_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata);
  • key - 提供给扫描的redis键上下文。
  • field - 字段名称,由调用者拥有,如果在此函数之后使用,则需要保留。
  • value - 值字符串或NULL用于设置类型,由调用者拥有,如果在此函数之后使用,则需要保留。
  • privdata - 提供给RedisModule_ScanKey的用户数据。

应该使用的方式:

 RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
 RedisModuleKey *key = RedisModule_OpenKey(...)
 while(RedisModule_ScanKey(key, c, callback, privateData));
 RedisModule_CloseKey(key);
 RedisModule_ScanCursorDestroy(c);

也可以在实际调用RedisModule_ScanKey期间获取锁时,从另一个线程使用此API,并每次重新打开键:

 RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();
 RedisModule_ThreadSafeContextLock(ctx);
 RedisModuleKey *key = RedisModule_OpenKey(...)
 while(RedisModule_ScanKey(ctx, c, callback, privateData)){
     RedisModule_CloseKey(key);
     RedisModule_ThreadSafeContextUnlock(ctx);
     // do some background job
     RedisModule_ThreadSafeContextLock(ctx);
     RedisModuleKey *key = RedisModule_OpenKey(...)
 }
 RedisModule_CloseKey(key);
 RedisModule_ScanCursorDestroy(c);

如果还有更多元素需要扫描,该函数将返回1,否则返回0,如果调用失败,可能会设置errno。也可以使用RedisModule_ScanCursorRestart重新启动现有的游标。

注意:在迭代对象时,某些操作是不安全的。例如,虽然API保证至少一次返回数据结构中从开始到结束一致存在的所有元素(参见HSCAN和类似命令的文档),但你操作的元素越多,可能会得到更多的重复项。通常,删除数据结构的当前元素是安全的,而删除你正在迭代的键则是不安全的。

模块 fork API

RedisModule_Fork

int RedisModule_Fork(RedisModuleForkDoneHandler cb, void *user_data);

自版本起可用: 6.0.0

创建一个后台子进程,使用主进程当前的冻结快照,您可以在后台进行一些处理,而不会影响/冻结流量,并且不需要线程和GIL锁定。 请注意,Redis只允许一个并发fork。 当子进程想要退出时,它应该调用RedisModule_ExitFromChild。 如果父进程想要杀死子进程,它应该调用RedisModule_KillForkChild 当子进程退出时(但不是被杀死时),父进程将执行完成处理程序回调。 返回值:失败时为-1,成功时父进程将获得子进程的正PID,子进程将获得0。

RedisModule_SendChildHeartbeat

void RedisModule_SendChildHeartbeat(double progress);

自版本起可用: 6.2.0

建议模块不时从子进程中调用此函数,以便它可以向父进程报告进度和COW内存,这些信息将在INFO中报告。progress参数应在0和1之间,或在不可用时为-1。

RedisModule_ExitFromChild

int RedisModule_ExitFromChild(int retcode);

自版本起可用: 6.0.0

当你想终止子进程时,从子进程调用。 retcode 将被提供给在父进程上执行的 done 处理程序。

RedisModule_KillForkChild

int RedisModule_KillForkChild(int child_pid);

自版本起可用: 6.0.0

可用于从父进程终止派生的子进程。 child_pid 将是 RedisModule_Fork 的返回值。

服务器钩子实现

RedisModule_SubscribeToServerEvent

int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx,
                                       RedisModuleEvent event,
                                       RedisModuleEventCallback callback);

自版本起可用: 6.0.0

注册以通过回调在指定的服务器事件发生时收到通知。回调函数将以事件作为参数调用,并且还有一个额外的参数,这是一个空指针,应转换为特定于事件的特定类型(但许多事件将仅使用NULL,因为它们没有额外的信息传递给回调)。

如果回调为NULL并且之前有订阅,模块将被取消订阅。如果之前有订阅且回调不为空,旧的回调将被新的回调替换。

回调必须是这种类型:

int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,
                                RedisModuleEvent eid,
                                uint64_t subevent,
                                void *data);

'ctx' 是一个普通的 Redis 模块上下文,回调函数可以使用它来调用其他模块的 API。'eid' 是事件本身,这在模块订阅了多个事件的情况下才有用:使用此结构的 'id' 字段可以检查事件是否是我们用此回调注册的事件之一。'subevent' 字段取决于触发的事件。

最后,'data' 指针可能会被填充,仅针对某些事件,提供更相关的数据。

以下是您可以用作'eid'的事件列表及相关子事件:

  • RedisModuleEvent_ReplicationRoleChanged:

    当实例从主服务器切换到从服务器或反之亦然时,会调用此事件,但是当从服务器仍然是从服务器但开始与不同的主服务器复制时,也会调用此事件。

    以下子事件可用:

    • REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_MASTER
    • REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA

    'data'字段可以由回调函数转换为RedisModuleReplicationInfo结构,该结构具有以下字段:

      int master; // 如果是主服务器则为true,如果是从服务器则为false
      char *masterhost; // 对于NOW_REPLICA,主服务器实例的主机名
      int masterport; // 对于NOW_REPLICA,主服务器实例的端口
      char *replid1; // 主复制ID
      char *replid2; // 辅助复制ID
      uint64_t repl1_offset; // 主复制偏移量
      uint64_t repl2_offset; // replid2有效性的偏移量
    
  • RedisModuleEvent_Persistence

    当RDB保存或AOF重写开始和结束时,会调用此事件。以下是可用的子事件:

    • REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START
    • REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START
    • REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START
    • REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START
    • REDISMODULE_SUBEVENT_PERSISTENCE_ENDED
    • REDISMODULE_SUBEVENT_PERSISTENCE_FAILED

    上述事件不仅在用户调用相关命令如BGSAVE时触发,还会在由于内部服务器触发器导致保存操作或AOF重写发生时触发。SYNC_RDB_START子事件由于SAVE命令、FLUSHALL或服务器关闭而在前台发生,其他RDB和AOF子事件在后台fork子进程中执行,因此模块采取的任何操作只能影响生成的AOF或RDB,而不会反映在父进程中并影响连接的客户端和命令。还要注意,在带有rdb-preamble的AOF情况下,AOF_START子事件可能会保存RDB内容。

  • RedisModuleEvent_FlushDB

    发生了FLUSHALL、FLUSHDB或内部刷新(例如由于复制,在副本同步之后)。以下子事件可用:

    • REDISMODULE_SUBEVENT_FLUSHDB_START
    • REDISMODULE_SUBEVENT_FLUSHDB_END

    数据指针可以转换为具有以下字段的RedisModuleFlushInfo结构:

      int32_t async;  // 如果刷新是在线程中完成的,则为真。
                      // 例如FLUSHALL ASYNC。
                      // 在这种情况下,END回调在数据库被放入线程的空闲列表后立即调用。
      int32_t dbnum;  // 刷新的数据库编号,-1表示在FLUSHALL操作中刷新所有数据库。
    

    开始事件在操作启动之前调用,因此允许回调在尚未释放的键空间上调用DBSIZE或其他操作。

  • RedisModuleEvent_Loading

    在加载操作时调用:在服务器启动时,以及在从主服务器加载RDB文件后的第一次同步时。 以下子事件可用:

    • REDISMODULE_SUBEVENT_LOADING_RDB_START
    • REDISMODULE_SUBEVENT_LOADING_AOF_START
    • REDISMODULE_SUBEVENT_LOADING_REPL_START
    • REDISMODULE_SUBEVENT_LOADING_ENDED
    • REDISMODULE_SUBEVENT_LOADING_FAILED

    请注意,在rdb-preamble的情况下,AOF加载可能以RDB数据开始,在这种情况下,您只会收到一个AOF_START事件。

  • RedisModuleEvent_ClientChange

    当客户端连接或断开时调用。 数据指针可以转换为RedisModuleClientInfo结构,记录在RedisModule_GetClientInfoById()中。 以下子事件可用:

    • REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED
    • REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED
  • RedisModuleEvent_Shutdown

    服务器正在关闭。没有可用的子事件。

  • RedisModuleEvent_ReplicaChange

    当实例(可以是主节点或副本节点)获得一个新的在线副本,或者由于断开连接而失去一个副本时,会调用此事件。 以下子事件可用:

    • REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE
    • REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE

    目前没有其他可用信息:未来的Redis版本将提供一个API来枚举连接的副本及其状态。

  • RedisModuleEvent_CronLoop

    每次Redis调用serverCron()函数以执行某些簿记操作时,都会触发此事件。需要不时执行操作的模块可以使用此回调。通常,Redis每秒调用此函数10次,但这会根据“hz”配置而变化。没有子事件可用。

    数据指针可以转换为具有以下字段的RedisModuleCronLoop结构:

      int32_t hz;  // 每秒大约的事件数。
    
  • RedisModuleEvent_MasterLinkChange

    这是为了通知副本,当复制链接与我们的主服务器变得功能正常(上线)或当它下线时。请注意,当我们刚连接到主服务器时,链接不被认为是上线的,只有在复制正确进行时才被认为是上线的。 以下是可用的子事件:

    • REDISMODULE_SUBEVENT_MASTER_LINK_UP
    • REDISMODULE_SUBEVENT_MASTER_LINK_DOWN
  • RedisModuleEvent_ModuleChange

    当加载新模块或卸载模块时,会调用此事件。 以下子事件可用:

    • REDISMODULE_SUBEVENT_MODULE_LOADED
    • REDISMODULE_SUBEVENT_MODULE_UNLOADED

    数据指针可以转换为具有以下字段的RedisModuleModuleChange结构:

      const char* module_name;  // 加载或卸载的模块名称。
      int32_t module_version;  // 模块版本。
    
  • RedisModuleEvent_LoadingProgress

    此事件在加载RDB或AOF文件时被重复调用。 以下子事件可用:

    • REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB
    • REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF

    数据指针可以转换为具有以下字段的RedisModuleLoadingProgress结构:

      int32_t hz;  // 每秒大约的事件数。
      int32_t progress;  // 0到1024之间的近似进度,
                         // 如果未知则为-1。
    
  • RedisModuleEvent_SwapDB

    当成功执行SWAPDB命令时,会调用此事件。 目前此事件调用没有可用的子事件。

    数据指针可以转换为具有以下字段的RedisModuleSwapDbInfo结构:

      int32_t dbnum_first;    // 交换的第一个数据库编号
      int32_t dbnum_second;   // 交换的第二个数据库编号
    
  • RedisModuleEvent_ReplBackup

    警告:自 Redis 7.0 起,复制备份事件已被弃用,并且永远不会触发。 请参阅 RedisModuleEvent_ReplAsyncLoad 以了解当 repl-diskless-load 设置为 swapdb 时,异步复制加载事件是如何触发的。

    当 repl-diskless-load 配置设置为 swapdb 时调用, 并且 Redis 需要备份当前数据库以便以后可能恢复。具有全局数据的模块, 可能还需要 aux_load 和 aux_save 回调,可能需要使用此通知来备份/恢复/丢弃其全局数据。 以下是可用的子事件:

    • REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE
    • REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE
    • REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD
  • RedisModuleEvent_ReplAsyncLoad

    当repl-diskless-load配置设置为swapdb并且与具有相同数据集历史(匹配的复制ID)的主节点进行复制时调用。 在这种情况下,Redis在从套接字加载新数据库到内存时,会提供当前数据集。 模块必须声明它们支持此机制才能激活它,通过REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD标志。 以下子事件可用:

    • REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED
    • REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED
    • REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED
  • RedisModuleEvent_ForkChild

    当fork子进程(AOFRW, RDBSAVE, 模块fork...)出生/死亡时调用 以下子事件可用:

    • REDISMODULE_SUBEVENT_FORK_CHILD_BORN
    • REDISMODULE_SUBEVENT_FORK_CHILD_DIED
  • RedisModuleEvent_EventLoop

    在每次事件循环迭代时调用,一次在事件循环进入睡眠之前,一次在它唤醒之后。 以下是可用的子事件:

    • REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP
    • REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP
  • RedisModule_Event_Config

    当配置事件发生时调用 以下子事件可用:

    • REDISMODULE_SUBEVENT_CONFIG_CHANGE

    数据指针可以转换为具有以下字段的RedisModuleConfigChange结构:

      const char **config_names; // 一个包含每个修改的配置项名称的C字符串指针数组
                                 // 每个修改的配置项的名称
      uint32_t num_changes;      // config_names数组中的元素数量
    
  • RedisModule_Event_Key

    当从键空间中移除一个键时调用。在事件中我们不能修改任何键。 以下是可用的子事件:

    • REDISMODULE_SUBEVENT_KEY_DELETED
    • REDISMODULE_SUBEVENT_KEY_EXPIRED
    • REDISMODULE_SUBEVENT_KEY_EVICTED
    • REDISMODULE_SUBEVENT_KEY_OVERWRITTEN

    数据指针可以转换为一个RedisModuleKeyInfo结构,该结构包含以下字段:

      RedisModuleKey *key;    // 键名
    

如果模块成功订阅了指定的事件,函数将返回REDISMODULE_OK。如果从错误的上下文中调用API或提供了不支持的事件,则返回REDISMODULE_ERR

RedisModule_IsSubEventSupported

int RedisModule_IsSubEventSupported(RedisModuleEvent event, int64_t subevent);

自以下版本可用: 6.0.9

对于给定的服务器事件和子事件,如果子事件不受支持,则返回零,否则返回非零。

模块配置 API

RedisModule_RegisterStringConfig

int RedisModule_RegisterStringConfig(RedisModuleCtx *ctx,
                                     const char *name,
                                     const char *default_val,
                                     unsigned int flags,
                                     RedisModuleConfigGetStringFunc getfn,
                                     RedisModuleConfigSetStringFunc setfn,
                                     RedisModuleConfigApplyFunc applyfn,
                                     void *privdata);

自版本起可用: 7.0.0

创建一个字符串配置,Redis用户可以通过Redis配置文件、CONFIG SETCONFIG GETCONFIG REWRITE命令与之交互。

实际的配置值由模块拥有,并且提供了getfnsetfn和可选的applyfn回调函数给Redis,以便访问或操作该值。getfn回调函数从模块中检索值,而setfn回调函数提供一个值以存储到模块配置中。可选的applyfn回调函数在CONFIG SET命令使用setfn回调函数修改一个或多个配置后被调用,并且可以用于在多个配置一起更改后原子地应用配置。如果单个CONFIG SET命令设置了多个带有applyfn回调函数的配置,并且它们的applyfn函数和privdata指针相同,则它们将被去重,并且回调函数只会运行一次。如果提供的值无效或无法使用,setfnapplyfn都可以返回错误。配置还声明了一个由Redis验证并提供给模块的值类型。配置系统提供了以下类型:

  • Redis 字符串:二进制安全字符串数据。
  • 枚举:在注册期间提供的有限数量的字符串标记之一。
  • 数值型:64位有符号整数,同时也支持最小值和最大值。
  • Bool: 是或否的值。

setfn 回调函数在值成功应用时应返回 REDISMODULE_OK。如果值无法应用,它也可以返回 REDISMODULE_ERR,并且可以通过 RedisModuleString 错误消息设置 *err 指针以提供给客户端。这个 RedisModuleString 将在从设置回调返回后被 redis 释放。

所有配置都通过名称、类型、默认值、在回调中可用的私有数据以及修改配置行为的几个标志进行注册。名称只能包含字母数字字符或破折号。支持的标志有:

  • REDISMODULE_CONFIG_DEFAULT: 配置的默认标志。这将创建一个可以在启动后修改的配置。
  • REDISMODULE_CONFIG_IMMUTABLE: 此配置只能在加载时提供。
  • REDISMODULE_CONFIG_SENSITIVE: 存储在此配置中的值将从所有日志中删除。
  • REDISMODULE_CONFIG_HIDDEN: 该名称在使用模式匹配的CONFIG GET中被隐藏。
  • REDISMODULE_CONFIG_PROTECTED: 此配置将仅根据enable-protected-configs的值进行修改。
  • REDISMODULE_CONFIG_DENY_LOADING: 当服务器正在加载数据时,此配置不可修改。
  • REDISMODULE_CONFIG_MEMORY: 对于数值配置,此配置将数据单位符号转换为等效的字节。
  • REDISMODULE_CONFIG_BITFLAGS: 对于枚举配置,此配置将允许多个条目组合为位标志。

如果未通过配置文件或命令行提供值,则在启动时使用默认值来设置该值。默认值也用于在配置重写时进行比较。

注释:

  1. 在字符串配置设置中,传递给设置回调的字符串将在执行后被释放,模块必须保留它。
  2. 在字符串配置中获取的字符串将不会被消耗,并且在执行后仍然有效。

示例实现:

RedisModuleString *strval;
int adjustable = 1;
RedisModuleString *getStringConfigCommand(const char *name, void *privdata) {
    return strval;
}

int setStringConfigCommand(const char *name, RedisModuleString *new, void *privdata, RedisModuleString **err) {
   if (adjustable) {
       RedisModule_Free(strval);
       RedisModule_RetainString(NULL, new);
       strval = new;
       return REDISMODULE_OK;
   }
   *err = RedisModule_CreateString(NULL, "Not adjustable.", 15);
   return REDISMODULE_ERR;
}
...
RedisModule_RegisterStringConfig(ctx, "string", NULL, REDISMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL);

如果注册失败,将返回REDISMODULE_ERR并设置以下errno之一:

  • EBUSY: 在RedisModule_OnLoad之外注册配置。
  • EINVAL: 提供的标志对于注册无效,或者配置名称包含无效字符。
  • EALREADY: 提供的配置名称已被使用。

RedisModule_RegisterBoolConfig

int RedisModule_RegisterBoolConfig(RedisModuleCtx *ctx,
                                   const char *name,
                                   int default_val,
                                   unsigned int flags,
                                   RedisModuleConfigGetBoolFunc getfn,
                                   RedisModuleConfigSetBoolFunc setfn,
                                   RedisModuleConfigApplyFunc applyfn,
                                   void *privdata);

自版本起可用: 7.0.0

创建一个布尔配置,服务器客户端可以通过CONFIG SETCONFIG GETCONFIG REWRITE命令与之交互。有关配置的详细信息,请参见RedisModule_RegisterStringConfig

RedisModule_RegisterEnumConfig

int RedisModule_RegisterEnumConfig(RedisModuleCtx *ctx,
                                   const char *name,
                                   int default_val,
                                   unsigned int flags,
                                   const char **enum_values,
                                   const int *int_values,
                                   int num_enum_vals,
                                   RedisModuleConfigGetEnumFunc getfn,
                                   RedisModuleConfigSetEnumFunc setfn,
                                   RedisModuleConfigApplyFunc applyfn,
                                   void *privdata);

自版本起可用: 7.0.0

创建一个枚举配置,服务器客户端可以通过CONFIG SETCONFIG GETCONFIG REWRITE命令与之交互。枚举配置是一组字符串标记到相应整数值的映射,其中字符串值暴露给Redis客户端,但传递给Redis和模块的值是整数值。这些值在enum_values中定义,这是一个以空字符结尾的C字符串数组,以及在int_vals中定义的枚举值数组,这些枚举值在enum_values中有一个索引伙伴。 示例实现: const char *enum_vals[3] = {"first", "second", "third"}; const int int_vals[3] = {0, 2, 4}; int enum_val = 0;

 int getEnumConfigCommand(const char *name, void *privdata) {
     return enum_val;
 }
  
 int setEnumConfigCommand(const char *name, int val, void *privdata, const char **err) {
     enum_val = val;
     return REDISMODULE_OK;
 }
 ...
 RedisModule_RegisterEnumConfig(ctx, "enum", 0, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 3, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);

请注意,您可以使用REDISMODULE_CONFIG_BITFLAGS,以便将多个枚举字符串组合成一个整数作为位标志,在这种情况下,您可能希望排序您的枚举,以便首选的组合首先出现。

有关配置的详细一般信息,请参见RedisModule_RegisterStringConfig

RedisModule_RegisterNumericConfig

int RedisModule_RegisterNumericConfig(RedisModuleCtx *ctx,
                                      const char *name,
                                      long long default_val,
                                      unsigned int flags,
                                      long long min,
                                      long long max,
                                      RedisModuleConfigGetNumericFunc getfn,
                                      RedisModuleConfigSetNumericFunc setfn,
                                      RedisModuleConfigApplyFunc applyfn,
                                      void *privdata);

自版本起可用: 7.0.0

创建一个整数配置,服务器客户端可以通过CONFIG SETCONFIG GETCONFIG REWRITE命令与之交互。有关配置的详细信息,请参见RedisModule_RegisterStringConfig

RedisModule_LoadConfigs

int RedisModule_LoadConfigs(RedisModuleCtx *ctx);

自版本起可用: 7.0.0

在模块加载时应用所有待处理的配置。这应该在所有配置已在RedisModule_OnLoad内为模块注册后调用。如果在RedisModule_OnLoad之外调用,这将返回REDISMODULE_ERR。当配置在MODULE LOADEX中提供或作为启动参数提供时,需要调用此API。

RDB 加载/保存 API

RedisModule_RdbStreamCreateFromFile

RedisModuleRdbStream *RedisModule_RdbStreamCreateFromFile(const char *filename);

自版本起可用: 7.2.0

创建一个流对象以将RDB保存到文件或从文件加载RDB。

此函数返回一个指向RedisModuleRdbStream的指针,该指针由调用者拥有。它需要调用RedisModule_RdbStreamFree()来释放该对象。

RedisModule_RdbStreamFree

void RedisModule_RdbStreamFree(RedisModuleRdbStream *stream);

自版本起可用: 7.2.0

释放一个RDB流对象。

RedisModule_RdbLoad

int RedisModule_RdbLoad(RedisModuleCtx *ctx,
                        RedisModuleRdbStream *stream,
                        int flags);

自版本起可用: 7.2.0

stream加载RDB文件。数据集将首先被清除,然后加载RDB文件。

flags 必须为零。此参数供将来使用。

成功时返回REDISMODULE_OK,否则返回REDISMODULE_ERR并相应地设置errno。

示例:

RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
RedisModule_RdbLoad(ctx, s, 0);
RedisModule_RdbStreamFree(s);

RedisModule_RdbSave

int RedisModule_RdbSave(RedisModuleCtx *ctx,
                        RedisModuleRdbStream *stream,
                        int flags);

自版本起可用: 7.2.0

将数据集保存到RDB流。

flags 必须为零。此参数供将来使用。

成功时返回REDISMODULE_OK,否则返回REDISMODULE_ERR,并相应地设置errno。

示例:

RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile("exp.rdb");
RedisModule_RdbSave(ctx, s, 0);
RedisModule_RdbStreamFree(s);

关键驱逐API

RedisModule_SetLRU

int RedisModule_SetLRU(RedisModuleKey *key, mstime_t lru_idle);

自版本起可用: 6.0.0

设置键的最后访问时间以用于基于LRU的淘汰。如果服务器的最大内存策略是基于LFU的,则不相关。值为空闲时间,以毫秒为单位。 如果LRU已更新,则返回REDISMODULE_OK,否则返回REDISMODULE_ERR

RedisModule_GetLRU

int RedisModule_GetLRU(RedisModuleKey *key, mstime_t *lru_idle);

自版本起可用: 6.0.0

获取键的最后访问时间。 值为空闲时间(以毫秒为单位),如果服务器的驱逐策略基于LFU,则值为-1。 如果键有效,则返回REDISMODULE_OK

RedisModule_SetLFU

int RedisModule_SetLFU(RedisModuleKey *key, long long lfu_freq);

自版本起可用: 6.0.0

设置键的访问频率。仅当服务器的最大内存策略基于LFU时相关。 频率是一个对数计数器,仅提供访问频率的指示(必须 <= 255)。 如果LFU已更新,则返回 REDISMODULE_OK,否则返回 REDISMODULE_ERR

RedisModule_GetLFU

int RedisModule_GetLFU(RedisModuleKey *key, long long *lfu_freq);

自版本起可用: 6.0.0

获取键的访问频率,如果服务器的淘汰策略不是基于LFU,则返回-1。 如果键有效,则返回REDISMODULE_OK

其他API

RedisModule_GetModuleOptionsAll

int RedisModule_GetModuleOptionsAll(void);

自版本起可用: 7.2.0

返回完整的模块选项标志掩码,模块可以使用返回值检查当前使用的 Redis 服务器版本是否支持某些模块选项。 示例:

   int supportedFlags = RedisModule_GetModuleOptionsAll();
   if (supportedFlags & REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS) {
         // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is supported
   } else{
         // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is not supported
   }

RedisModule_GetContextFlagsAll

int RedisModule_GetContextFlagsAll(void);

自以下版本可用: 6.0.9

返回完整的ContextFlags掩码,使用返回值模块可以检查当前使用的redis服务器版本是否支持某些标志集。 示例:

   int supportedFlags = RedisModule_GetContextFlagsAll();
   if (supportedFlags & REDISMODULE_CTX_FLAGS_MULTI) {
         // REDISMODULE_CTX_FLAGS_MULTI is supported
   } else{
         // REDISMODULE_CTX_FLAGS_MULTI is not supported
   }

RedisModule_GetKeyspaceNotificationFlagsAll

int RedisModule_GetKeyspaceNotificationFlagsAll(void);

自以下版本可用: 6.0.9

返回完整的KeyspaceNotification掩码,使用返回值模块可以检查当前使用的redis服务器版本是否支持某些标志集。 示例:

   int supportedFlags = RedisModule_GetKeyspaceNotificationFlagsAll();
   if (supportedFlags & REDISMODULE_NOTIFY_LOADED) {
         // REDISMODULE_NOTIFY_LOADED is supported
   } else{
         // REDISMODULE_NOTIFY_LOADED is not supported
   }

RedisModule_GetServerVersion

int RedisModule_GetServerVersion(void);

自以下版本可用: 6.0.9

返回Redis版本,格式为0x00MMmmpp。 例如,对于6.0.7,返回值将为0x00060007。

RedisModule_GetTypeMethodVersion

int RedisModule_GetTypeMethodVersion(void);

自版本起可用: 6.2.0

返回当前redis-server运行时REDISMODULE_TYPE_METHOD_VERSION的值。 你可以在调用RedisModule_CreateDataType时使用它,以了解RedisModuleTypeMethods的哪些字段将被支持,哪些将被忽略。

RedisModule_ModuleTypeReplaceValue

int RedisModule_ModuleTypeReplaceValue(RedisModuleKey *key,
                                       moduleType *mt,
                                       void *new_value,
                                       void **old_value);

自版本起可用: 6.0.0

替换分配给模块类型的值。

密钥必须开放以供写入,具有现有值,并且具有与调用者指定的模块类型匹配的模块类型。

RedisModule_ModuleTypeSetValue()不同,后者会释放旧值,而这个函数只是简单地将旧值与新值交换。

函数成功时返回 REDISMODULE_OK,错误时返回 REDISMODULE_ERR,例如:

  1. 密钥未打开以供写入。
  2. 键不是模块数据类型键。
  3. Key 是一个模块数据类型,不是 'mt'。

如果 old_value 不为空,则通过引用返回旧值。

RedisModule_GetCommandKeysWithFlags

int *RedisModule_GetCommandKeysWithFlags(RedisModuleCtx *ctx,
                                         RedisModuleString **argv,
                                         int argc,
                                         int *num_keys,
                                         int **out_flags);

自版本起可用: 7.0.0

对于指定的命令,解析其参数并返回一个包含所有键名参数索引的数组。这个函数本质上是执行COMMAND GETKEYS的一种更高效的方式。

out_flags 参数是可选的,可以设置为 NULL。 当提供时,它将填充与返回数组的键索引匹配的 REDISMODULE_CMD_KEY_ 标志。

返回值为NULL表示指定的命令没有键,或者出现错误情况。错误情况通过设置errno来指示,如下所示:

  • ENOENT: 指定的命令不存在。
  • EINVAL: 指定的命令参数数量无效。

注意:返回的数组不是Redis模块对象,因此即使使用自动内存管理,它也不会自动释放。调用者必须显式调用RedisModule_Free()来释放它,如果使用了out_flags指针,同样需要释放。

RedisModule_GetCommandKeys

int *RedisModule_GetCommandKeys(RedisModuleCtx *ctx,
                                RedisModuleString **argv,
                                int argc,
                                int *num_keys);

自以下版本可用: 6.0.9

RedisModule_GetCommandKeysWithFlags相同,当不需要标志时。

RedisModule_GetCurrentCommandName

const char *RedisModule_GetCurrentCommandName(RedisModuleCtx *ctx);

自版本起可用: 6.2.5

返回当前正在运行的命令的名称

Defrag API

RedisModule_RegisterDefragFunc

int RedisModule_RegisterDefragFunc(RedisModuleCtx *ctx,
                                   RedisModuleDefragFunc cb);

自版本起可用: 6.2.0

为全局数据注册一个碎片整理回调,即模块可能分配的与特定数据类型无关的任何内容。

RedisModule_DefragShouldStop

int RedisModule_DefragShouldStop(RedisModuleDefragCtx *ctx);

自版本起可用: 6.2.0

当数据类型整理回调遍历复杂结构时,应定期调用此函数。返回值为零(假)表示回调可以继续其工作。非零值(真)表示它应该停止。

当停止时,回调函数可以使用RedisModule_DefragCursorSet()来存储其位置,以便稍后可以使用RedisModule_DefragCursorGet()来继续碎片整理。

当停止并且还有更多工作需要完成时,回调函数应返回1。否则,应返回0。

注意:模块应考虑此函数的调用频率,因此通常在调用之间进行小批量工作是有意义的。

RedisModule_DefragCursorSet

int RedisModule_DefragCursorSet(RedisModuleDefragCtx *ctx,
                                unsigned long cursor);

自版本起可用: 6.2.0

存储任意游标值以供将来重复使用。

只有在RedisModule_DefragShouldStop()返回非零值并且碎片整理回调即将退出而没有完全迭代其数据类型时,才应调用此函数。

此行为保留给执行延迟碎片整理的情况。对于实现了free_effort回调并返回大于碎片整理配置指令'active-defrag-max-scan-fields'的free_effort值的键,选择延迟碎片整理。

较小的键、未实现free_effort或全局碎片整理回调的键在延迟碎片整理模式下不会被调用。在这些情况下,调用此函数将返回REDISMODULE_ERR

游标可能被模块用来表示模块数据类型的某些进度。模块还可以在本地存储与游标相关的附加信息,并使用游标作为标志,指示何时开始遍历新键。这是可能的,因为API保证不会同时执行多个键的碎片整理。

RedisModule_DefragCursorGet

int RedisModule_DefragCursorGet(RedisModuleDefragCtx *ctx,
                                unsigned long *cursor);

自版本起可用: 6.2.0

获取之前使用RedisModule_DefragCursorSet()存储的游标值。

如果没有为延迟的碎片整理操作调用,将返回REDISMODULE_ERR,并且应忽略游标。有关碎片整理游标的更多详细信息,请参见RedisModule_DefragCursorSet()

RedisModule_DefragAlloc

void *RedisModule_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr);

自版本起可用: 6.2.0

对之前由RedisModule_AllocRedisModule_Calloc等分配的内存进行碎片整理。 碎片整理过程包括分配一个新的内存块并将内容复制到其中,类似于realloc()

如果不需要碎片整理,则返回NULL,并且该操作没有其他效果。

如果返回一个非NULL值,调用者应使用新指针而不是旧指针,并更新对旧指针的任何引用,旧指针不得再次使用。

RedisModule_DefragRedisModuleString

RedisModuleString *RedisModule_DefragRedisModuleString(RedisModuleDefragCtx *ctx,
                                                       RedisModuleString *str);

自版本起可用: 6.2.0

对先前由RedisModule_AllocRedisModule_Calloc等分配的RedisModuleString进行碎片整理。 有关碎片整理过程如何工作的更多信息,请参见RedisModule_DefragAlloc()

注意:只能对具有单一引用的字符串进行碎片整理。 通常这意味着使用RedisModule_RetainStringRedisModule_HoldString保留的字符串 可能无法进行碎片整理。一个例外是命令参数,如果由模块保留, 最终将只有一个引用(因为Redis端的引用在命令回调返回后立即被丢弃)。

RedisModule_GetKeyNameFromDefragCtx

const RedisModuleString *RedisModule_GetKeyNameFromDefragCtx(RedisModuleDefragCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的键的名称。 不能保证键名称始终可用,因此这可能返回NULL。

RedisModule_GetDbIdFromDefragCtx

int RedisModule_GetDbIdFromDefragCtx(RedisModuleDefragCtx *ctx);

自版本起可用: 7.0.0

返回当前正在处理的键的数据库ID。 不能保证此信息始终可用,因此可能返回-1。

函数索引

RATE THIS PAGE
Back to top ↑