Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redis: To set timeout for a key value pair in Set

Tags:

redis

I have a Redis set with key 'a' and value '1','2','3'. Is there a way to set different expire time for each key-value pair in the set.

For example ('a','1') should expire after 60 seconds where as ('a','2') should expire after 120 seconds.

like image 212
user3218088 Avatar asked Jun 08 '14 10:06

user3218088


1 Answers

Unfortunately, no. Redis' "containers" (i.e. lists, hashes, sets and sorted sets) do not support per-member expiry, although this functionality has been requested many times in the past.

You can, however, implement your own logic to achieve that result. There are several possible approaches to address this - here's one example. Instead of using a set, use a sorted set (ZSET) and set each member's score to its expiry time using epoch values. This type of workflow could be implemented using a Lua script for example. To add members use something like:

redis.call('zadd', KEYS[1], os.time()+ARGV[1], ARGV[2])

and EVAL it using '1 a 60 1' and '1 a 120 2' as arguments, per your example. To actually "expire" the items from the set, you'll need to delete them once their time has passed. You can do that either by implementing a periodical process that scans your list or upon accessing it. For example, the following Lua can be used to expire members:

redis.call('zremrangebyscore', KEYS[1], '-inf', os.time())

and EVAL it using '1 a' as arguments per your example.

EDIT: How to achieve the above using Python

import time
import redis

def add(r, key, ttl, member):
    r.zadd(key, member, int(time.time()+ttl))

def expire(r, key):
    r.zremrangebyscore(key, '-inf', int(time.time()))

...

r = redis.Redis()
add(r, 'a', 1, 60)
add(r, 'a', 2, 120)

# periodically or before every operation do
expire(r, 'a')
like image 77
Itamar Haber Avatar answered Sep 21 '22 14:09

Itamar Haber