How can I update a redis value without affecting the remaining TTL?

55,549

Solution 1

The KEEPTTL option will be added to SET in redis>=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.

Solution 2

According to Redis documentation, the SET command removes the TTL because the key is overwritten.

However you can use the EVAL command to evaluate a Lua script to do it automatically for you.

The script bellow checks for the TTL value of a key, if the value is positive it calls SETEX with the new value and using the remaining TTL.

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

Example:

> set key 123

OK

> expire key 120

(integer) 1

... after some seconds

> 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"

Solution 3

Maybe the INCR, INCRBY, DECR, etc. can help you. They don't modify the TTL.

> setex test 3600 13
OK

> incr test
(integer) 14

> ttl test
(integer) 3554

http://redis.io/commands/INCR

Solution 4

It is possible to change the value without affecting TTL on it's key by changing value bits one by one according to new value by using SETBIT.

Disadvantage of this approach however is obviously performance impact, especially if value is quite big.

NOTE: It is advisable to execute this in transaction (multi exec) block

Maintaining TTL by ourselves by

  • Fetching current TTL

  • Set new value

  • Restoring TTL after setting value

    is obviously not advisable due to unknown durability of the commands executed.

Another alternative is to use List as data type and after adding new value to the list with LPUSH use LTRIM to maintain size of list to single element. This wont change TTL on the key.

Share:
55,549

Related videos on Youtube

paulkon
Author by

paulkon

Updated on July 09, 2022

Comments

  • paulkon
    paulkon almost 2 years

    Is it possible to SET redis keys without removing their existing ttl? The only way I know of at the present time is to find out the ttl and do a SETEX but that seems less accurate.

  • Muhammad Ali
    Muhammad Ali about 2 years
    this worked perfectly for me as I was dealing with integer values.