INCREX
将键的数值增加一个数字并设置其过期时间。如果键不存在,则使用 0 作为初始值。
语法
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]
引入版本:8.8.0
复杂度摘要:O(1)
在单个原子操作中,将 key 中存储的数值增加或减少指定的量,并具有可选的上限/下限和过期控制。如果该键不存在,则在执行操作之前将其设置为 0。如果键包含错误类型的值或无法解释为数字的字符串,则会返回错误。
与 INCR 和 INCRBY 不同,INCREX 返回一个包含两个元素的数组:增量后键的新值和实际应用的增量。当计算结果超出显式 LBOUND/UBOUND 或类型限制时,默认情况下会跳过该操作并使用 [current_value, 0] 进行回复,同时保持键及其 TTL 不变。 SATURATE 标志改变了这种行为,因此结果被限制在边界处。
必需参数
key
要递增的键的名称。
可选参数
BYFLOAT increment | BYINT increment
指定增量数量和类型:
BYFLOAT increment:将值增加给定的 long-double float。键的现有值可以是整数或浮点数,因为整数可以无损地提升为浮点数。会产生 NaN 或 Infinity 的结果将被拒绝。BYINT increment:将值增加给定的 64 位有符号整数。增量可以是负值以减少值。BYINT要求键的现有值是整数类型;存储的浮点数(例如"1.5")无法解析回整数。这与INCR/INCRBY(仅整数)和INCRBYFLOAT(两者都接受)一致。
如果未指定 BYFLOAT 和 BYINT,则键以整数模式递增 1。 BYFLOAT 和 BYINT 是互斥的。
LBOUND lowerbound
设置结果值的下限。如果计算结果低于 lowerbound,则跳过该操作,回复为 [current_value, 0](或使用 SATURATE 标志将结果置于 lowerbound)。省略时,界限为整数模式下的 LLONG_MIN 或 BYFLOAT 模式下的界限为 -LDBL_MAX。当指定了两者时,LBOUND 必须小于或等于 UBOUND。
UBOUND upperbound
设置结果值的上限。如果计算结果超过 upperbound,则跳过该操作并回复 [current_value, 0](或使用 SATURATE 标志将结果限制在 upperbound)。省略时,界限为整数模式下的 LLONG_MAX 或 BYFLOAT 模式下的界限为 LDBL_MAX。当两者都指定时,UBOUND 必须大于或等于 LBOUND。
SATURATE
指定后,越界结果的上限为 UBOUND 或下限为 LBOUND(或者在未给出显式界限时饱和到类型限制)。回复的第二个元素反映了饱和增量。如果增量在整数模式下无法表示为 64 位有符号整数,或者在 BYFLOAT 模式下会产生无穷大,则会返回错误。任何到期选项仍按指定应用。
边界违规包括超出显式 LBOUND/UBOUND 以及在未给出显式边界时溢出类型限制。
expiration flags
INCREX 命令支持一组修改其过期行为的选项:
EX seconds:设置指定的过期时间,单位为秒(正整数)。PX milliseconds:设置指定的过期时间,单位为毫秒(正整数)。EXAT unix-time-seconds:设置键过期的指定 Unix 时间(以秒为单位)(正整数)。PXAT unix-time-milliseconds:设置键过期的指定 Unix 时间(以毫秒为单位)(正整数)。PERSIST:删除与键相关的过期时间。
如果没有给出过期选项,则保留键的现有 TTL(如果有)。
ENX
仅当键当前没有 TTL/过期时才设置 TTL/过期。如果键已有 TTL,则仍应用增量,但 TTL 保持不变。 ENX 可以确保窗口计数器速率限制器的 TTL 仅在创建时设置,并且不会在后续令牌请求时重置。ENX 必须与 EX、PX、EXAT 或 PXAT 组合,并且与 PERSIST 不兼容。
示例
默认增量(按1),如果key不存在则从0开始:
redis> DEL mykey1
(integer) 0
redis> INCREX mykey1
1) (integer) 1
2) (integer) 1
redis> INCREX mykey1
1) (integer) 2
2) (integer) 1
使用 BYINT 递增特定整数,包括负递增递减:
redis> SET mykey2 100
OK
redis> INCREX mykey2 BYINT 5
1) (integer) 105
2) (integer) 5
redis> INCREX mykey2 BYINT -10
1) (integer) 95
2) (integer) -10
使用 BYFLOAT 以浮点数递增:
redis> SET mykey3 1.5
OK
redis> INCREX mykey3 BYFLOAT 0.25
1) "1.75"
2) "0.25"
使用 EX 设置每个增量的过期时间:
redis> DEL mykey4
(integer) 0
redis> INCREX mykey4 BYINT 1 EX 100
1) (integer) 1
2) (integer) 1
redis> TTL mykey4
(integer) 100
仅当键没有现有 TTL 时,才使用 ENX 设置过期时间。无论以下情况,始终都会应用增量:
redis> SET mykey5 10
OK
redis> INCREX mykey5 BYINT 1 EX 100 ENX
1) (integer) 11
2) (integer) 1
redis> TTL mykey5
(integer) 100
redis> SET mykey5 10 EX 500
OK
redis> INCREX mykey5 BYINT 1 EX 10 ENX
1) (integer) 11
2) (integer) 1
redis> TTL mykey5
(integer) 500
使用 PERSIST 在递增时删除键的过期时间:
redis> SET mykey6 5 EX 1000
OK
redis> TTL mykey6
(integer) 1000
redis> INCREX mykey6 BYINT 1 PERSIST
1) (integer) 6
2) (integer) 1
redis> TTL mykey6
(integer) -1
当结果超出 UBOUND 时,将默认越界行为与 SATURATE 进行比较。默认情况下,该键保持不变,并且回复报告零增量;使用 SATURATE,结果被限制在边界处,并且回复反映了饱和增量:
redis> SET mykey7 99
OK
redis> INCREX mykey7 BYINT 5 UBOUND 100
1) (integer) 99
2) (integer) 0
redis> SET mykey7 99
OK
redis> INCREX mykey7 BYINT 5 UBOUND 100 SATURATE
1) (integer) 100
2) (integer) 1
详细说明
模式:窗口计数器速率限制器
常见的速率限制模式需要原子地递增计数器并设置其过期时间。对于普通 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() # rate limit exceeded
双活数据库
在主动-主动数据库中,每个副本根据其自己的本地值强制执行 LBOUND 和 UBOUND。不同副本同时接受的增量可以在副本同步后将合并值推至 UBOUND 以上或低于 LBOUND。当合并的值超出范围时,每个副本都会拒绝进一步的增量,直到该值返回到范围内或键过期。
例如,有两个副本和一个从 0 开始的键:
Replica 1: INCREX k BYINT 6 UBOUND 10 -> 1) 6 2) 6
Replica 2: INCREX k BYINT 6 UBOUND 10 -> 1) 6 2) 6
After synchronization, both replicas: k = 12
每个副本接受其增量,因为其本地结果 6 在界限内。合并后的值 12 超过 UBOUND。
Redis Software 与 Redis Cloud 兼容性
| Redis 软件 |
Redis Cloud |
说明 |
|---|---|---|
| ✅ 标准 |
❌ 标准 |
*在主动-主动数据库中,副本对其本地值强制执行边界,因此合并的值可能会超出它们。请参阅 双活数据库。 |
返回值
RESP2
数组回复:二元素数组:
- 新价值 — 递增后键的值,或者当越界结果导致操作被跳过时不变的当前值。
- 实际增量 — 实际应用的增量。当
SATURATE将结果限制在某个界限时,可能与请求的增量不同;当超出界限的结果导致操作被跳过时,始终为0。
两个元素在整数模式下均为 整数回复(默认为 BYINT),在 BYFLOAT 模式下为表示浮点值的 批量字符串回复。
RESP3
数组回复:二元素数组:
- 新价值 — 递增后键的值,或者当越界结果导致操作被跳过时不变的当前值。
- 实际增量 — 实际应用的增量。当
SATURATE将结果限制在某个界限时,可能与请求的增量不同;当超出界限的结果导致操作被跳过时,始终为0。
资料来源:Redis 官方 INCREX 文档;中文内容参考 Redis 文档许可。