Redis,会话到期和反向查找

Rok*_*okG 18 redis

我目前正在构建一个Web应用程序,并希望使用Redis来存储会话.登录时,会话将插入具有相应用户ID的Redis,并在15分钟时设置到期时间.我现在想要为会话实现反向查找(获取具有特定用户ID的会话).这里的问题是,因为我无法搜索Redis密钥空间,如何实现它.一种方法是为每个userId设置一个redis,包含所有会话id.但是由于Redis不允许集合中的项目到期,并且会话设置为过期,因此集合中将存在大量不存在的会话ID.

在密钥到期时从集合中删除ID的最佳方法是什么?或者,有没有更好的方法来实现我想要的东西(反向查找)?

Did*_*zia 23

在Redis(2.6)的当前版本分支上,当项目过期时,您无法收到通知.它可能会随着下一个版本而改变.

在此期间,为了支持您的要求,您需要手动实施到期通知支持.所以你有了:

session:<sessionid> -> a hash storing your session data - one of the field is <userid>
user:<userid> -> a set of <sessionid>
Run Code Online (Sandbox Code Playgroud)

您需要在会话到期时从用户集中删除sessionid.因此,您可以维护其分数为时间戳的其他有序集.

为用户100创建会话10时:

MULTI
HMSET session:10 userid:100 ... other session data ...
SADD user:100 10
ZADD to_be_expired <current timestamp + session timeout> 10
EXEC
Run Code Online (Sandbox Code Playgroud)

然后,您需要构建一个守护进程,该守护进程将轮询zset以识别要过期的会话(ZRANGEBYSCORE).对于每个过期的会话,它必须维护数据结构:

  • 从zset中弹出会话(ZREMRANGEBYRANK)
  • 检索会话用户ID(HMGET)
  • 删除会话(DEL)
  • 从用户标识集(SREM)中删除会话

主要困难是确保守护进程轮询和处理项目时没有竞争条件.请参阅我对此问题的回答,了解如何实施:

如何处理会话过期基于redis?


por*_*ors 5

在较新版本的Redis(2.8.0及以上)的KEYSPACE通知expired事件的支持。即,当具有 TTL 的密钥到期时,会触发此事件。

这是订阅内容:

'__keyevent@0__:expired'
Run Code Online (Sandbox Code Playgroud)

因此,订阅此事件允许您为所有会话拥有一个索引,并且您可以在密钥过期时从索引中删除该密钥。

例子:

使用排序集作为二级索引,以 uid 作为权重:

ZADD "idx-session-uid" <uid> <sessionkey>
Run Code Online (Sandbox Code Playgroud)

使用以下命令搜索特定用户的会话密钥:

ZRANGEBYSCORE "idx-session-uid" <uid> <uid>
Run Code Online (Sandbox Code Playgroud)

当会话被删除或过期时,我们会执行以下操作:

ZREM "idx-session-uid" <sessionkey>
Run Code Online (Sandbox Code Playgroud)