Suppose an use case:
I wanna store authentication tokens in redis that is associated with a client application. The best way to implement this is use a hash table which key is the application id and the field is the token id and the value of the field is the token data.
The token could be expired or manually be revoked by delete command, and if I wanna to revoke all tokens which is associated with an application, I could simply delete the hash table.
Since the hash table doesn't support expire time of field, I'm implementing this by a formatted key [appid]-[tokenid] and when I'm revoking all tokens of an application, I have to scan the keys which start with [appid]- and delete them, it takes much of time.
So, I'm wondering if redis could support expire time of a field in hash table in the future? Or could I implement the above requirement in another better way?
Thanks.
Comment From: jpassaro
Alternative:
Use a ZSET with scores as time (seconds since epoch). Manual revocation = ZREM, revoke all = DEL as with your suggestion.
When you need to validate:
MULTI
ZREMRANGEBYSCORE $app_id -inf $expiry_date
ZSCORE $app_id $current_token
EXEC
where $expiry_date is current time minus 7*86400 (a week) or whatever suits you, and $current_token is the token you want to check on. Based on what you're saying, you could probably use your $app_id as the key for the ZSET.
Comment From: fengpeiyuan
@jpassaro good idea,but the value(token data) is not stored.
Comment From: jpassaro
Fair enough. You could augment with a hash, and periodically trim it like so.
Fetch valid tokens and possibly-valid data:
ZREMRANGEBYSCORE tokens:$app_id:time -inf $expiry_date
ZRANGE tokens:$app_id:time 0 -1
HGETALL tokens:$app_id:data
Client app or lua script can trim the hash as needed and then store it:
MULTI
HMSET tokens:$app_id:data:temp $data
RENAME tokens:$app_id:data:temp tokens:$app_id:data
EXEC
There might be better solutions and I'd be curious to hear them. However I hope this is a reasonable demonstration that existing Redis functionality can support OP's case without adding a new feature.
Comment From: CloudMarc
Here's another alternative:
Note that top level commands SET and GET are addressing one big hash. And of course these support EXPIRE. What they don't support are things like hkeys, hvals, hgetall. However, note that KEYS() and HKEYS() are both O(n) operations. So if each hash has a prefix, you can use keys("prefix*") to replace hkeys(). Likewise, one could write lua scripts that correspond to hvals and hgetall.
m
On Thu, Apr 28, 2016 at 8:15 AM, jpassaro notifications@github.com wrote:
Fair enough. You could augment with a hash, and periodically trim it like so.
Fetch valid tokens and possibly-valid data:
ZREMRANGEBYSCORE tokens:$app_id:time -inf $expiry_date ZRANGE 0 -1 tokens:$app_id:time HGETALL tokens:$app_id:data
Client app or lua script can trim the hash as needed and then store it:
MULTI HMSET tokens:$app_id:data:temp $data RENAME tokens:$app_id:data:temp tokens:$app_id:data EXEC
There might be better solutions and I'd be curious to hear them. However I hope this is a reasonable demonstration that existing Redis functionality can support OP's case without adding a new feature.
— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/antirez/redis/issues/3192#issuecomment-215460245
Comment From: fengpeiyuan
@CloudMarc can you show an example for this case?
Comment From: kirkvicent
1、不妨在每个value里面加上一个时间戳,自己在应用中对比时间 2、尝试给不同的field提升至顶级key 3、肯定还有其他解决办法
Comment From: romange
For the protocol, it has been implemented in Dragonfly: https://github.com/dragonflydb/dragonfly/pull/817
Comment From: moticless
Heads up, we've started implementing hash field expiration, and it's planned for an upcoming release.