Redis, session expiration, and reverse lookup

On the current release branch of Redis (2.6), you cannot have notifications when items are expired. It will probably change with the next versions.

In the meantime, to support your requirement, you need to manually implement expiration notification support. So you have:

session:<sessionid> -> a hash storing your session data - one of the field is <userid>
user:<userid> -> a set of <sessionid>

You need to remove sessionid from the user set when the session expires. So you can maintain a additional sorted set whose score is a timestamp.

When you create session 10 for user 100:

MULTI
HMSET session:10 userid:100 ... other session data ...
SADD user:100 10
ZADD to_be_expired <current timestamp + session timeout> 10
EXEC

Then, you need to build a daemon which will poll the zset to identify the session to expire (ZRANGEBYSCORE). For each expired session, it has to maintain the data structure:

  • pop the session out of the zset (ZREMRANGEBYRANK)
  • retrieve session userid (HMGET)
  • delete session (DEL)
  • remove session from userid set (SREM)

The main difficulty is to ensure there is no race conditions when the daemon polls and processes the items. See my answer to this question to see how it can be implemented:

how to handle session expire basing redis?


In more recent versions of Redis (2.8.0 and up) Keyspace Notifications for expired events are supported. I.e. when a key with a TTL expires this event is triggered.

This is what to subscribe to:

'__keyevent@0__:expired'

So subscribing to this event allows you to have a single index for all sessions and you can remove the key from the index when the key expires.

Example:

Use a sorted set as a secondary index with the uid as the weight:

ZADD "idx-session-uid" <uid> <sessionkey>

Search for sessionkeys for a specific user with:

ZRANGEBYSCORE "idx-session-uid" <uid> <uid>

When a session is deleted or expired we do:

ZREM "idx-session-uid" <sessionkey>

Tags:

Redis