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



是否可以在不删除现有 ttl 的情况下SET redis 密钥?我目前所知道的唯一方法是找出 ttl 并做一个SETEX但这似乎不太准确。

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

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.

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

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

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

local ttl = redis.call('ttl', ARGV[1]) 如果 ttl

> 0 则返回 redis.call('SETEX', ARGV[1], ttl, ARGV[2]) end

例:

>设置键 123

还行

>过期密钥 120

(整数) 1

。几秒钟后

> ttl 键

(整数) 97

> eval "local ttl = redis.call('ttl', ARGV[1]) 如果 ttl

> 0 则返回 redis.call('SETEX', ARGV[1], ttl, ARGV[2]) end" 0 key 987

还行

> ttl 键

96

>获取密钥

"987"

也许INCRINCRBYDECR等可以帮助你。他们不会修改 TTL。

> setex test 3600 13
OK
> incr test
(integer) 14
> ttl test
(integer) 3554

http://redis.io/commands/INCR

通过使用 SETBIT 根据新值逐个更改值位,可以在不影响其键上的 TTL 的情况下更改值。

然而,这种方法的缺点显然会影响性能,尤其是在价值相当大的情况下。

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

自行维护 TTL

  • 获取当前 TTL

  • 设置新值

  • 设置值后恢复 TTL

    显然不建议,因为执行的命令的持久性未知。

另一种选择是使用 List 作为数据类型,在使用 LPUSH 向列表中添加新值后,使用 LTRIM 将列表的大小保持为单个元素。这不会更改密钥上的 TTL。

这是一个检查现有 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);
        });
      };

有一种方法可以从 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

出于某种原因,这种功能不起作用:

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

相反,我需要写这个:

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

文档可在此处找到:https://www.npmjs.com/package//redis

最新更新