如何处理会话过期基础的Redis?(how to handle session expire bas

2019-06-26 18:45发布

我想实现基于Redis的一个会话存储。 我愿把会话数据为Redis的。 但我不知道如何处理会话过期。 我可以通过所有Redis的密钥(会话ID)循环和评估上次访问时间和最大空闲时间,所以我需要所有的钥匙加载到客户端,并有可能成为千米的会话密钥,并可能导致我很穷/ O表演。
我想让Redis的管理到期,但目前还没有监听器或回调时的关键到期,所以不可能触发HttpSessionListener。 有什么建议?

Answer 1:

因此,你需要在会​​话中的Redis到期通知你的应用程序。

虽然Redis的不支持此功能,有一些你可以用它来实现它的技巧。

更新:从2.8.0版本,Redis的不支持此http://redis.io/topics/notifications

首先,人们都在思考这件事:这个还在讨论中,但它可能会被添加到Redis的未来版本。 请参见下面的问题:

  • https://github.com/antirez/redis/issues/83
  • https://github.com/antirez/redis/issues/594

现在,这里有一些解决方案可以与目前Redis的版本使用。

解决方法1:修补的Redis

其实,当Redis的执行增加一个简单的通知密钥过期并不难。 它可以通过添加10行至Redis的源代码文件db.c来实现。 下面是一个例子:

https://gist.github.com/3258233

这个简短的帖子补丁的#expired列表中的关键,如果密钥已过期,并用“@”字符(任意选择)开始。 它可以很容易地适应您的需求。

它是那么微不足道使用过期或SETEX命令来设置过期时间为你的会话对象,并写一个小的守护进程环路上BRPOP从“#expired”名单中退出,并在传播你的应用程序的通知。

很重要的一点是要了解到期机制中的Redis是如何工作的。 实际上有呼气两个不同的路径,都在同一时间活性:

  • 懒惰(无源)的机制。 期满可以各自一个键被访问时发生。

  • 活动机制。 内部作业进行定期(随机)样本一批具有到期一套钥匙,试图找到那些过期。

需要注意的是,上述补丁正常工作与两个路径。

其结果是Redis的到期时间是不准确的。 如果所有的按键都失效,但只有一个是即将到期,且其不被访问,有效期满作业可能需要几分钟才能找到问题的关键和过期了。 如果你需要在通知一定的准确性,这是不是要走的路。

溶液2:用zsets模拟到期

这里的想法是不依赖于Redis的密钥过期机制,而是通过一个附加的索引加上轮询守护模拟。 它可以与未修改的Redis 2.6版本。

每一个会话被添加到Redis的时候,你可以运行:

MULTI
SET <session id> <session content>
ZADD to_be_expired <current timestamp + session timeout> <session id>
EXEC

该to_be_expired排序set只是访问应该到期的第一密钥的有效途径。 守护程序可以轮询使用以下Lua的服务器端脚本to_be_expired:

local res = redis.call('ZRANGEBYSCORE',KEYS[1], 0, ARGV[1], 'LIMIT', 0, 10 )
if #res > 0 then
   redis.call( 'ZREMRANGEBYRANK', KEYS[1], 0, #res-1 )
   return res
else
   return false
end

启动脚本的命令是:

EVAL <script> 1 to_be_expired <current timestamp>

该守护进程将获得最多10个项目。 对于每个人,它必须使用DEL命令删除会议,并通知应用程序。 如果一个项目是实际处理(即Lua的脚本的回报是不为空),应立即循环,否则会被引入守护1秒的等待状态。

得益于Lua中,可以并行推出几款轮询守护程序(脚本保证,因为密钥是从由Lua的脚本本身to_be_expired删除某次会议将只处理一次)。

解决方案3:使用外部分布式计时器

另一个解决方案是依赖于外部分布式定时器。 在豆茎轻量级排队系统是一个很好的可能性

每个会话在系统中加入的时间,应用程序的帖子的会话ID到队列豆茎具有延迟对应于所述会话超时。 守护程序监听到队列中。 当它出队的项目,这意味着会话已过期。 它只是清理在Redis的会话,并通知应用程序。



文章来源: how to handle session expire basing redis?