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

35

有没有可能在不移除Redis键的现有ttl的情况下进行SET操作?目前我所知道的唯一方法是查找ttl并执行SETEX,但这似乎不够准确。

7个回答

33

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

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.

21
根据 Redis 文档SET 命令会移除 TTL 时间,因为键被覆盖了。
但是您可以使用 EVAL 命令来评估 Lua 脚本,以便自动完成此操作。
下面的脚本检查一个键的 TTL 值,如果该值是正数,则使用新值和剩余 TTL 调用 SETEX

local ttl = redis.call('ttl', ARGV[1]) if ttl > 0 then return redis.call('SETEX', ARGV[1], ttl, ARGV[2]) end

示例:

> set key 123

OK

> expire key 120

(integer) 1

... 几秒钟后

> ttl key

(integer) 97

> eval "local ttl = redis.call('ttl', ARGV[1]) if ttl > 0 then return redis.call('SETEX', ARGV[1], ttl, ARGV[2]) end" 0 key 987

OK

> ttl key

96

> get key

"987"


16

也许 INCR, INCRBY, DECR 等命令可以帮助您,在不修改 TTL 的情况下实现操作。

> setex test 3600 13
OK

> incr test
(integer) 14

> ttl test
(integer) 3554

http://redis.io/commands/INCR


这对我非常有效,因为我正在处理整数值。 - Muhammad Ali

2
使用SETBIT可以逐位更改值以根据新值更改值而不影响其键的TTL。但是,这种方法的缺点显然是性能影响,特别是如果值相当大。

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

通过以下方式自行维护TTL:

  • 获取当前TTL

  • 设置新值

  • 设置值后恢复TTL

    由于执行的命令的耐久性未知,因此显然不可取。

另一种选择是使用List作为数据类型,在使用LPUSH将新值添加到列表后,使用LTRIM来将列表大小维护为单个元素。这不会更改键的TTL。


0

从Redis中获取剩余的TTL有一种方法。

Redis中维护TTL

  1. 获取当前的TTL
  2. 设置新值
  3. 在设置值后恢复TTL

示例:

// This function helps to get the  Remaining TTL from the redis.
        const  getRemainingTTL=(key)=> {  
            return new Promise((resolve,reject)=>{
                redisClient.TTL(key,(err,value)=>{
                    if(err)reject(err);
                    resolve(value);
                });
            });
        };
     let remainingTTL=await getRemainingTTL(otpSetKey);
     console.log('remainingTTL',remainingTTL);

     redisClient.set(key,newValue,'EX',exTime ); // set agin

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);
        });
      };

-1

出于某种原因,这种函数对我来说无法正常工作:

 redisSender.set('tenMinWaitTime', avg, 'KEEPTTL')

但我需要写成这样:

 redisSender.set('tenMinWaitTime', avg, { KEEPTTL: true })

文档可以在这里找到: https://www.npmjs.com/package//redis


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接