【问题标题】:How can I update a redis value without affecting the remaining TTL?如何在不影响剩余 TTL 的情况下更新 redis 值?
【发布时间】:2014-03-20 18:40:27
【问题描述】:

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

【问题讨论】:

    标签: redis node-redis


    【解决方案1】:

    根据 Redis documentation 的说法,SET 命令会移除 TTL,因为密钥已被覆盖。

    但是,您可以使用 EVAL 命令来评估 Lua 脚本以自动为您完成。

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

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

    例子:

    > 设置键 123

    好的

    > 过期密钥 120

    (整数)1

    ...几秒钟后

    > ttl 键

    (整数)97

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

    好的

    > ttl 键

    96

    > 获取密钥

    “987”

    【讨论】:

      【解决方案2】:

      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.
      

      【讨论】:

        【解决方案3】:

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

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

        http://redis.io/commands/INCR

        【讨论】:

        • 这对我来说非常有效,因为我正在处理整数值。
        【解决方案4】:

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

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

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

        自行维护TTL

        • 获取当前 TTL

        • 设置新值

        • 设置值后恢复TTL

          由于所执行命令的持久性未知,显然不建议使用。

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-12
              • 2015-12-03
              • 1970-01-01
              • 1970-01-01
              • 2016-01-18
              • 2023-03-15
              相关资源
              最近更新 更多