在使用Redis时, 通常会使用EXPIRE
, PEXPIRE
系列函数设置生存时间, 当需要获取超时时间时使用TTL
, PTTL
获取剩余的生存时间。
同样的, 还可以使用EXPIREAT
, PEXPIREAT
以unix timestamp格式设置超时时间点, 但需要注意的是, Redis 7.0 之前没有函数能获取设置timestamp, 只能使用TTL
, PTTL
获取剩余的生存时间。
在实际使用中, 经常需要比较新旧生存周期的大小来决定是否更新数据, 如果你很幸运的使用7.0及之后的版本, 可以使用EXPIREAT
, PEXPIREAT
配合GT
参数来设置过期时间, 如果新的过期时间小于已有过期时间, 则会返回0
。
那么老版本的Redis该如何实现这种功能呢?
在Redis中使用TIME
命令可以获取当当前的timestamp, 加上TTL
, PTTL
获取的值之后就可以得到原本设置的过期时间。
需要注意的是TIME
命令返回两个字符串(比如 “1672400893” 和 “528370” ), 第一个字符串中的数字代表以秒计时的unix timestamp, 第二个字符串中的数字代表当前这一秒中已经过去多少微秒。
为了完成数学计算, 需要使用tonumber
函数将字符串转换为数字, 如果只需要秒及精度, 只使用第一个字符串的返回值即可, 如果需要毫秒级精度, 则需要将第一个数字乘1000, 将第二个数字除以1000, 并将两个数字相加。
以下LUA展示了如何实现带超时的SET命令毫秒时间戳的比较, 只有当新的超时时间戳大于已有的超时时间戳, 新的value才能成功设置, 返回服务器最终采用的时间戳, 客户端应该比较返回时间戳与传入时间戳是否相等, 若不等于则说明设置失败。
参数
KEYS[1]: SET 命令的 KEY
AEGV[1]: SET 命令的 VAL
AEGV[2]: 超时时间戳(ms)
1 | local expirePTTL = redis.call('PTTL', KEYS[1]) |