如何在不影响剩余TTL的情况下更新redis值?

时间:2014-02-20 03:13:02

标签: redis node-redis

是否可以SET redis键而不删除现有的ttl?我目前唯一知道的方法是找出ttl并做一个SETEX,但这似乎不太准确。

5 个答案:

答案 0 :(得分:11)

根据Redis documentationSET命令会删除TTL,因为密钥会被覆盖。

但是,您可以使用EVAL命令评估Lua脚本,以便自动为您执行此操作。

下面的脚本检查密钥的TTL值,如果值为正,则使用新值并使用剩余的TTL调用SETEX

  

local ttl = redis.call('ttl',ARGV [1])if ttl> 0然后返回redis.call('SETEX',ARGV [1],ttl,ARGV [2])结束

示例:

  

>设置键123

     

     

>到期密钥120

     

(整数)1

......几秒钟后

  

> ttl key

     

(整数)97

     

> eval“local ttl = redis.call('ttl',ARGV [1])if ttl> 0然后返回redis.call('SETEX',ARGV [1],ttl,ARGV [2])结束”0键987

     

     

> ttl key

     

96

     

>得到钥匙

     

“987”

答案 1 :(得分:10)

KEEPTTL 选项将在redis> = 6.0中添加到 SET

https://redis.io/commands/set

https://github.com/antirez/redis/pull/6679

The SET command supports a set of options that modify its behavior:

EX seconds -- Set the specified expire time, in seconds.
PX milliseconds -- Set the specified expire time, in milliseconds.
NX -- Only set the key if it does not already exist.
XX -- Only set the key if it already exist.
(!) KEEPTTL -- Retain the time to live associated with the key.

答案 2 :(得分:6)

也许INCRINCRBYDECR等可以为您提供帮助。他们没有修改TTL。

> setex test 3600 13
OK

> incr test
(integer) 14

> ttl test
(integer) 3554

http://redis.io/commands/INCR

答案 3 :(得分:1)

可以通过使用SETBIT根据新值逐个更改值位来更改值而不影响其上的TTL。

然而,这种方法的缺点显然是性能影响,特别是如果价值非常大的话。

注意:建议在事务(多个exec)块中执行此操作

自己维护TTL

  • 获取当前TTL
  • 设置新值
  • 设置值

    后恢复TTL 由于执行的命令的持久性未知,

    显然是不可取的。

另一种方法是使用List作为数据类型,并在使用LPUSH将新值添加到列表后使用LTRIM将list的大小保持为单个元素。这不会改变钥匙上的TTL。

答案 4 :(得分:0)

这是检查现有TTL并在需要时使用它的功能。

过期参数 0 - 使用现有的到期时间,> 0 - 设置新的过期时间,未定义 - 没有过期时间。

    /**
       * update an item. preserve ttl or set a new one
       * @param {object} handle the redis handle
       * @param {string} key the key
       * @param {*} content the content - if an object it'll get stringified
       * @param {number||null} expire if a number > 0 its an expire time, 0 
means keep existing ttl, undefined means no expiry
       * @return {Promise}
       */
      ns.updateItem = function (handle , key , content,expire) {

        // first we have to get the expiry time if needed
        return (expire === 0 ? handle.ttl(key) : Promise.resolve (expire))
        .then (function (e) {

          // deal with errors retrieving the ttl (-1 no expiry, -2 no existing record)
          var ttl = e > 0 ? e :  undefined;

          // stingify the data if needed
          var data = typeof content === "object" ? JSON.stringify(content) : content;

          // set and apply ttl if needed
          return ttl ? handle.set (key, data , "EX", ttl) : handle.set (key,data);
        });
      };