*Redis increx 命令

*语法

INCREX key [BYFLOAT increment | BYINT increment]
 [LBOUND lowerbound] [UBOUND upperbound] [SATURATE]
 [EX seconds | PX milliseconds | EXAT unix-time-seconds| PXAT unix-time-milliseconds | PERSIST] [ENX]

在单个原子操作中将存储在 key 处的数值增加指定量,具有可选的上/下边界和过期控制。 如果键不存在,则在执行操作前将其设置为 0。 如果键包含错误类型的值或无法解释为数字的字符串,则返回错误。

INCRINCRBY 不同,INCREX 返回一个包含两个元素的数组:增量后的键的新值,以及实际应用的增量。当计算结果将超出显式 LBOUND/UBOUND 或类型限制时,默认行为是跳过操作并回复 [current_value, 0],保持键及其 TTL 不变。SATURATE 标志改变此行为,使结果在边界处被限制。

*必需参数

{{< details open >}}{{< summary >}}{{< code >}}key{{< /code >}}{{< /summary >}}

要递增的键的名称。

{{< /details >}}

*可选参数

{{< details open >}}{{< summary >}}{{< code >}}BYFLOAT increment | BYINT increment{{< /code >}}{{< /summary >}}

指定增量数量和类型:

  • BYFLOAT increment: 使用给定的长双精度浮点数增加值。键的现有值可以是整数或浮点数,因为整数可以无损地提升为浮点数。会产生 NaN 或 Infinity 的结果将被拒绝。
  • BYINT increment: 使用给定的 64 位有符号整数增加值。增量可以为负数以递减值。BYINT 要求键的现有值为整数类型;存储的浮点数如 "1.5" 无法解析回整数。这与 INCR/INCRBY(仅整数)和 INCRBYFLOAT(接受两者)一致。

如果未指定 BYFLOATBYINT,键以整数模式递增 1BYFLOATBYINT 互斥。

{{< /details >}}

{{< details open >}}{{< summary >}}{{< code >}}LBOUND lowerbound{{< /code >}}{{< /summary >}}

设置结果的值的下界。如果计算结果将低于 lowerbound,则操作被跳过,回复为 [current_value, 0](或使用 SATURATE 标志将结果限制在 lowerbound)。省略时,整数模式下边界为 LLONG_MINBYFLOAT 模式下为 -LDBL_MAX。当两者都指定时,LBOUND 必须小于或等于 UBOUND

{{< /details >}}

{{< details open >}}{{< summary >}}{{< code >}}UBOUND upperbound{{< /code >}}{{< /summary >}}

设置结果的值的上界。如果计算结果将超过 upperbound,则操作被跳过,回复为 [current_value, 0](或使用 SATURATE 标志将结果限制在 upperbound)。省略时,整数模式上边界为 LLONG_MAXBYFLOAT 模式下为 LDBL_MAX。当两者都指定时,UBOUND 必须大于或等于 LBOUND

{{< /details >}}

{{< details open >}}{{< summary >}}{{< code >}}SATURATE{{< /code >}}{{< /summary >}}

指定时,越界结果将在 UBOUND 处被限制或在 LBOUND 处被下限(或当没有显式边界时饱和到类型限制)。回复的第二个元素反映饱和增量。如果增量在整数模式下无法表示为 64 位有符号整数,或在 BYFLOAT 模式下会产生 Infinity,则返回错误。任何过期选项仍按指定应用。

越界违规包括超出显式 LBOUND/UBOUND 和在没有显式边界时溢出类型限制。

{{< /details >}}

{{< details open >}}{{< summary >}}{{< code >}}过期标志{{< /code >}}{{< /summary >}}

INCREX 命令支持一组修改其过期行为的选项:

  • EX seconds: 设置指定的过期时间(秒)(正整数)。
  • PX milliseconds: 设置指定的过期时间(毫秒)(正整数)。
  • EXAT unix-time-seconds: 设置键将过期的指定 Unix 时间(秒)(正整数)。
  • PXAT unix-time-milliseconds: 设置键将过期的指定 Unix 时间(毫秒)(正整数)。
  • PERSIST: 删除与键关联的过期时间。

当未给出过期选项时,保留键的现有 TTL(如果有)。

{{< /details >}}

{{< details open >}}{{< summary >}}{{< code >}}ENX{{< /code >}}{{< /summary >}}

仅当键当前没有 TTL/过期时间时才设置 TTL/过期时间。如果键已有 TTL,则仍应用增量但 TTL 保持不变。ENX 可以确保窗口计数器速率限制器的 TTL 仅在创建时设置,而在后续令牌请求时不重置。ENX 必须与 EXPXEXATPXAT 组合,且与 PERSIST 不兼容。

{{< /details >}}

*示例

默认增量(按 1),如果键不存在则从 0 开始:

{{< redis-cli >}} DEL mykey1 INCREX mykey1 INCREX mykey1 {{< /redis-cli >}}

使用 BYINT 按特定整数递增,包括使用负增量递减:

{{< redis-cli >}} SET mykey2 100 INCREX mykey2 BYINT 5 INCREX mykey2 BYINT -10 {{< /redis-cli >}}

使用 BYFLOAT 按浮点数递增:

{{< redis-cli >}} SET mykey3 1.5 INCREX mykey3 BYFLOAT 0.25 {{< /redis-cli >}}

使用 EX 在每次递增时设置过期时间:

{{< redis-cli >}} DEL mykey4 INCREX mykey4 BYINT 1 EX 100 TTL mykey4 {{< /redis-cli >}}

使用 ENX 仅在键没有现有 TTL 时设置过期时间。无论是否设置过期,增量始终应用:

{{< redis-cli >}} SET mykey5 10 INCREX mykey5 BYINT 1 EX 100 ENX TTL mykey5 SET mykey5 10 EX 500 INCREX mykey5 BYINT 1 EX 10 ENX TTL mykey5 {{< /redis-cli >}}

使用 PERSIST 在递增时删除键的过期时间:

{{< redis-cli >}} SET mykey6 5 EX 1000 TTL mykey6 INCREX mykey6 BYINT 1 PERSIST TTL mykey6 {{< /redis-cli >}}

比较默认越界行为与 SATURATE,当结果将超过 UBOUND 时。默认情况下键保持不变,回复报告零增量;使用 SATURATE 时结果在边界处被限制,回复反映饱和增量:

{{< redis-cli >}} SET mykey7 99 INCREX mykey7 BYINT 5 UBOUND 100 SET mykey7 99 INCREX mykey7 BYINT 5 UBOUND 100 SATURATE {{< /redis-cli >}}

*模式:窗口计数器速率限制器

常见的速率限制模式需要原子地递增计数器并设置其过期时间。使用普通的 INCREXPIRE,这通常需要 Lua 脚本来实现原子性。

INCREX 只需要单个原生命令。UBOUND 强制执行速率上限——默认情况下,一旦达到上限,操作被跳过——ENX 确保在前一个窗口已过期时创建具有正确持续时间的新窗口;如果窗口已存在,则不会延长。当计数器已达到上限时,actual_increment0,为调用者提供即时反馈,无需额外读取或错误处理:

new_val, actual_incr = redis.execute_command(
    "INCREX", f"ratelimit:{user_id}",
    "BYINT", 1, "UBOUND", 100,
    "EX", 60, "ENX",
)
if actual_incr == 0:
    reject_request()  # 速率限制已超出

*返回信息