*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。
如果键包含错误类型的值或无法解释为数字的字符串,则返回错误。
与 INCR 和 INCRBY 不同,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(接受两者)一致。
如果未指定 BYFLOAT 或 BYINT,键以整数模式递增 1。BYFLOAT 和 BYINT 互斥。
{{< /details >}}
{{< details open >}}{{< summary >}}{{< code >}}LBOUND lowerbound{{< /code >}}{{< /summary >}}
设置结果的值的下界。如果计算结果将低于 lowerbound,则操作被跳过,回复为 [current_value, 0](或使用 SATURATE 标志将结果限制在 lowerbound)。省略时,整数模式下边界为 LLONG_MIN,BYFLOAT 模式下为 -LDBL_MAX。当两者都指定时,LBOUND 必须小于或等于 UBOUND。
{{< /details >}}
{{< details open >}}{{< summary >}}{{< code >}}UBOUND upperbound{{< /code >}}{{< /summary >}}
设置结果的值的上界。如果计算结果将超过 upperbound,则操作被跳过,回复为 [current_value, 0](或使用 SATURATE 标志将结果限制在 upperbound)。省略时,整数模式上边界为 LLONG_MAX,BYFLOAT 模式下为 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 必须与 EX、PX、EXAT 或 PXAT 组合,且与 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 >}}
*模式:窗口计数器速率限制器
常见的速率限制模式需要原子地递增计数器并设置其过期时间。使用普通的 INCR 和 EXPIRE,这通常需要 Lua 脚本来实现原子性。
INCREX 只需要单个原生命令。UBOUND 强制执行速率上限——默认情况下,一旦达到上限,操作被跳过——ENX 确保在前一个窗口已过期时创建具有正确持续时间的新窗口;如果窗口已存在,则不会延长。当计数器已达到上限时,actual_increment 为 0,为调用者提供即时反馈,无需额外读取或错误处理:
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() # 速率限制已超出