Updating a Hash key does not remove the timeout

628 views
Skip to first unread message

Daniel Mezzatto

unread,
Mar 12, 2012, 9:13:48 AM3/12/12
to redi...@googlegroups.com
According to the EXPIRE command documentation (http://redis.io/commands/expire), if a timeout is set to a key and then some change is made to that key, the timeout is to be removed:

"If key is updated before the timeout has expired, then the timeout is removed as if the PERSIST command was invoked on key."

Updating a Hash key does not remove the timeout:

redis 127.0.0.1:6379> hset x a 1
(integer) 1
redis 127.0.0.1:6379> ttl x
(integer) -1
redis 127.0.0.1:6379> expire x 60
(integer) 1
redis 127.0.0.1:6379> ttl x
(integer) 59
redis 127.0.0.1:6379> hset x a 2
(integer) 0
redis 127.0.0.1:6379> ttl x
(integer) 55

Looks like the timeout is removed only for the "simple" key-value type (not lists, hashs etc).
This is a bug or an expected behavior?

Jay A. Kreibich

unread,
Mar 12, 2012, 9:28:11 AM3/12/12
to redi...@googlegroups.com
On Mon, Mar 12, 2012 at 06:13:48AM -0700, Daniel Mezzatto scratched on the wall:

> According to the EXPIRE command documentation (
> http://redis.io/commands/expire), if a timeout is set to a key and then
> some change is made to that key, the timeout is to be removed:
>
> *"If key is updated before the timeout has expired, then the timeout is
> removed as if the PERSIST <http://redis.io/commands/persist> command was
> invoked on key."*


> Looks like the timeout is removed only for the "simple" key-value type (not
> lists, hashs etc).

> This is a bug or an expected behavior?

Expected. Essentially, if the key's value is completely replaced
(e.g. a new string value is set) it will clear the TTL. If the
key's value is simply modified, without a total replacement, the
TTL remains.

In this context, "modified" means pretty much any operation on a
container type value (hash, list, set, sorted-set), or a command like
SETRANGE or SETBIT on a string value.


If you think about how different Redis structures are typically used
in a cache, this is usually the desired behavior. A cached string,
such as a pre-rendered webpage, typically needs a brand new TTL. A
cached object, such as a database row, typically still needs to
expire, even if a single field was modified.

-j


--
Jay A. Kreibich < J A Y @ K R E I B I.C H >

"Intelligence is like underwear: it is important that you have it,
but showing it to the wrong people has the tendency to make them
feel uncomfortable." -- Angela Johnson

Daniel Mezzatto

unread,
Mar 12, 2012, 2:12:39 PM3/12/12
to redi...@googlegroups.com, j...@kreibi.ch
Hmm... it not like that. The timeout removal does not have anything to do with "complete replacement" of the key. Redis source code calls removeExpire() only inside setKey() and persistCommand(). My question was about the correctness of such call only when the SET command is issued.

Any other thoughts?

Jay A. Kreibich

unread,
Mar 12, 2012, 3:27:27 PM3/12/12
to Daniel Mezzatto, redi...@googlegroups.com
On Mon, Mar 12, 2012 at 11:12:39AM -0700, Daniel Mezzatto scratched on the wall:

> Hmm... it not like that. The timeout removal does not have anything to do
> with "complete replacement" of the key. Redis source code calls
> removeExpire() only inside setKey() and persistCommand().

And setKey() completely discards the old key value, completely
replacing the old value with the new value. Again, this is different
from most container operators where the value is only modified... For
example, if you add an element to a hash, you do not copy the whole
hash, add the new element, set the top level key to point to the
brand new hash, and then destroy the whole old hash-- you simply
modify the existing hash value. Key values that are replaced have
their TTLs cleared. Key values that are modified keep their TTLs.

Also note that a new container can only be implicitly created, which
means you can never replace an existing key (with a TTL) with an
empty/new container. Only with string values can you completely
replace an existing key in one command, so only when setting string
values will the TTL be cleared.

> My question was
> about the correctness of such call only when the SET command is issued.

If you're only talking about SET (and MSET, GETSET, etc.), then it
operates exactly as the docs specify... if you issue a SET command
against an existing volatile key (i.e. one that has a TTL), the TTL
will be cleared and the key will become persistent. Same with
GETSET, MSET, and similar commands.

In that case, to reset the TTL to some known value, you can issue
a SET/EXPIRE pair, or use SETEX. This is the typical desired
behavior for a cache.

If you want to set a new string value without resetting the TTL, you
can use SETRANGE with an offset of 0. This is more unusual.

-j

> Any other thoughts?
>
>
> Em segunda-feira, 12 de mar??o de 2012 10h28min11s UTC-3, Jay Kreibich

Salvatore Sanfilippo

unread,
Mar 12, 2012, 4:32:50 PM3/12/12
to redi...@googlegroups.com, Daniel Mezzatto
Jay's reply is just perfect, I just want to add that this is very
similar to what you get with high level programming languages.

You can think to "SET, MSET, ..." as the assignment operator "=".

a = "foo" ; # SET a foo

Instead most other Redis commands operate in the value, like calling a method:

foo.lpush("bar")

If you think at it from this point of view the semantics is pretty obvious.

Salvatore

> --
> You received this message because you are subscribed to the Google Groups "Redis DB" group.
> To post to this group, send email to redi...@googlegroups.com.
> To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.
>

--
Salvatore 'antirez' Sanfilippo
open source developer - VMware

http://invece.org
"We are what we repeatedly do. Excellence, therefore, is not an act,
but a habit." -- Aristotele

Message has been deleted

Salvatore Sanfilippo

unread,
Mar 15, 2012, 5:38:11 AM3/15/12
to redi...@googlegroups.com
Update: I modified the EXPIRE documentation to make it better.

Please let me know if it can be easily improved more.

Salvatore

Daniel Mezzatto

unread,
Mar 15, 2012, 9:52:44 AM3/15/12
to redi...@googlegroups.com
Much better now. Thanks :)
Salvatore

> To unsubscribe from this group, send email to redis-db+unsubscribe@googlegroups.com.

> For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.
>



--
Salvatore 'antirez' Sanfilippo
open source developer - VMware

http://invece.org
"We are what we repeatedly do. Excellence, therefore, is not an act,
but a habit." -- Aristotele

whe...@gmail.com

unread,
Mar 16, 2012, 2:38:11 AM3/16/12
to redi...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages