Redis MULTI事务中设置key过期后仍出现TTL为-1的问题求解
问题根因
- 最核心的错误是代码中
SET操作的key与后续INCR、PTTL操作的key不一致:SET用的是<key>变量,INCR和PTTL用的是rdskey变量。当两个变量值不相等时:- 如果
<key>不存在,SET会成功给<key>设置带过期的初始值0 - 但
INCR操作的是rdskey,如果这个rdskey不存在,Redis的INCR命令会自动创建该key,默认不带过期时间,直接返回值1,这就导致了rdskey的TTL为-1,完全符合你遇到的异常表现。
- 如果
- 如果确认两个key变量值完全一致,还有一种极低概率的场景:你使用的Redis客户端存在语法兼容问题,
SET命令的EX、NX参数未被正确识别传递,导致SET执行后虽然key创建成功,但没有设置过期时间。
解决方案
- 统一事务中所有操作的key变量,确保
SET、INCR、PTTL操作的是同一个key,同时给命令参数加上字符串引号,避免部分客户端将参数识别为变量,修改后参考代码如下:
options.client .multi() .set(rdskey, 0, 'EX', <expiry_time>, 'NX') .incr(rdskey) .pttl(rdskey) .exec(function (err, replies) { if (err) { return cb(err); } cb( null, replies[1], replies[2] ); });
- 可额外增加兜底校验逻辑:如果事务返回的PTTL结果为-1,主动调用
EXPIRE命令给key设置过期时间,避免永久存在的key导致限流规则失效。
内容的提问来源于stack exchange,提问作者Mish Nia
相关产品推荐
相关产品推荐

