前言

在日常开发中,我们有时候需要对在线用户进行管理,由于登录信息是可以过期的,那么使用RDBMS存储有点不合时宜,所以NoSQL存储更为合理。网上找了一些资料,但貌似似乎都不太完备,以下为个人理解的Redis实现在线用户列表的方案。

方案概述

一开始,就需要考虑如何存储、使用什么数据结构。首先string,hash,set可以被排除,因为都无法满足排序问题,现在剩下list和zset,list虽然是有序的,但元素(会话session)过期无法维护,那现在就只剩下zset了,zset首先可以满足排序问题,那元素(会话session)过期该如何维护呢?

由于zset的每个元素存在score,那么可以把登录时间戳作为score进行存储,顺序关系很自然就确定了,再来看如何维护过期元素呢?既然score是登录时间戳,那么只要元素的score小于当前时间-会话有效时间,那么这些key就是过期的,删除这些元素来达到维护在线用户列表的目的。

添加在线用户和倒序用户列表命令示例,添加元素示例中的userN为代表要存储的内容,具体存什么后面再讨论。

# 添加有序集合元素模拟用户登录时间戳和要存储的用户对象数据
127.0.0.1:6379> zadd online:user 1 user1 2 user2 3 user3 4 user4 5 user5
(integer) 5
# 默认是按score升序排序的
127.0.0.1:6379> zrange online:user 0 -1
1) "user1"
2) "user2"
3) "user3"
4) "user4"
5) "user5"
127.0.0.1:6379>
# 按score倒序查看 +inf表示正无穷大,-inf表示负无穷大,倒序时,命令是从大到小,java api中是从小到大,使用的时候请注意
127.0.0.1:6379> zrevrangebyscore online:user +inf -inf
1) "user5"
2) "user4"
3) "user3"
4) "user2"
5) "user1"

删除过期元素,最后的2表示当前时间和过期时间的差值。

# 删除过期元素
127.0.0.1:6379> zremrangebyscore online:user 0 2
(integer) 2
127.0.0.1:6379> zrevrangebyscore online:user +inf 0 #查看删除过期元素的集合元素
1) "user5"
2) "user4"
3) "user3"
127.0.0.1:6379>

以上可以完成在线用户列表的添加查询和过期删除,由于用户的会话过期是自动过期的,上面完成的只是手动过期(删除)示例,我们可以通过定时任务执行上面的删除过期的命令来达到自动维护的目的,这里的定时任务周期可以用5秒甚至10秒,毕竟没必要完全做到精确,脏数据就是定时之间可能存在的过期元素。

查询

既然查询的是在线用户列表,那么查询的内容一定要在在线用户列表中有所维护或者关联,所以查询条件就很重要,什么维度查询呢?用户相关?登录相关?终端相关?支持查询的条件越多,存储的内容就越复杂,我们这里统一按用户相关查询来描述。

那么往在线用户列表的有序集合中添加元素时,元素的内容该如何组合?这个时候需要分两个维度来看,是否支持多端登录?

不支持多端登录

不支持多端登录的方案相对简单,存储内容就按用户唯一标识存储即可,查询条件可以支持和用户唯一标识有关系的数据(即可以通过查询条件查询出对应的userId),这样将所有的查询转移到userId上,再从在线用户列表中获取是否存在,存在则返回,并获取登录用户的缓存(key为用户唯一标识),缓存不存在说明在线用户列表存在过期的脏数据,此时删除列表中的元素,返回即可,如果存在登录用户缓存,则封装用户列表需要的数据返回。

支持多端登录

支持多端登录,由于zset是不可重复的,那么在线用户列表的元素内容就不能只存一个用户唯一标识了,需要添加会话标识和用户唯一标识来一起存储,此时还需要再维护一个用户唯一标识和所有会话session的关系,这样就可以查询一个用户登录的所有在线列表信息了,该关系可以使用set存储,查询的时候,先查询到关系数据,在通过关系数据组装key,再去会话列表中查询,存在则返回,并获取登录用户的缓存(key为用户唯一标识),缓存不存在说明在线用户列表存在过期的脏数据,此时删除列表中的元素和关系中的元素,返回即可,如果存在登录用户缓存,则封装用户列表需要的数据返回。

# 此处存储的value元素按 用户唯一标识:sessionId的结构来存储
# 存储时两个同时添加
127.0.0.1:6379> zadd online:user  61 6:session6-1 62 6:session6-2 63 6:session6-3
(integer) 3
127.0.0.1:6379> sadd online:user:6 session6-1 session6-2 session6-3 #维护用户唯一标识和session的关系
(integer) 3
# 查询添加的元素
127.0.0.1:6379> zrange online:user 0 -1
1) "user3"
2) "user4"
3) "user5"
4) "6:session6-1"
5) "6:session6-2"
6) "6:session6-3"
127.0.0.1:6379>
127.0.0.1:6379> smembers online:user:6
1) "session6-3"
2) "session6-2"
3) "session6-1"
127.0.0.1:6379>
​
# 过期时(删除)时两个同时删除
127.0.0.1:6379> srem online:user:6 session6-2
(integer) 1
127.0.0.1:6379> zrem online:user 6:session6-2
(integer) 1
127.0.0.1:6379>
​
# 删除过期元素后查看元素
127.0.0.1:6379> zrange online:user 0 -1
1) "user3"
2) "user4"
3) "user5"
4) "6:session6-1"
5) "6:session6-3"
127.0.0.1:6379> smembers online:user:6
1) "session6-3"
2) "session6-1"
127.0.0.1:6379>

踢人

不支持多端登录

不支多端登录的,踢除登录时,删除用户登录缓存和在线用户列表缓存元素即可。

支持多端登录

支持多端登录的,踢除登录时,除了删除用户登录缓存和在线用户列表缓存元素外,还需要删除用户唯一标识和session的关系集合中的元素。

Redis实现在线用户列表(按登录时间排序、可查询、踢人)相关推荐

  1. 用redis+jwt保存在线用户和获得在线用户列表、踢出用户示例

    文章目录 redis工具类 用户实体类 token配置 service层保存和查询在线用户 工具类 获得用户浏览器等其他信息 controller层 redis工具类 import org.sprin ...

  2. Python 模拟登录AUSU路由器获取在线用户列表

    Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. Requests: 让 HTTP 服务人类 前段时间撸了一个斐讯K2P的路由器,最近下车了,刷了一个梅林固件,今 ...

  3. JAVA实现QQ:实现文字聊天、QQ用户登录、拉取在线用户列表、无异常退出、私聊、发文件、下载文件、离线留言、服务端推送新闻等功能(后端无界面,Utilty源码在后面、)

    这个仿QQ项目是参考韩顺平老师的多线程课程做的,因为个人觉得非常有意义特别是让我对多线程通信又了一个新的理解因此我准备写一篇总结(如果觉得视频太长可以参考下): 具体视频地址:大家给韩老师一键三连[韩 ...

  4. [转载]Asp.Net在线用户列表的開發匯總

    这是转载的别人的一篇,解决了困扰我已久的问题,虽然文章里少了两张图,但是不影响阅读. 1.在线用户列表的实现 在ASP时代,要实现一个网站的在线用户列表显示功能的惯用做法是修改global.asa文件 ...

  5. ASP.NET在线用户列表精确版——解决用户意外退出在线列表无法及时更新问题

    最近所做的一个项目需要用到的在线用户列表,上网搜索了一下发现现有的解决方案对用户意外退出的处理均不是太理想.一般来说,用户离开系统的方式有三种:主动注销.会话超时.直接关闭浏览器,对于前两种,我们很容 ...

  6. 实现在线用户列表的简单方法

    因最近时间空点,写点个人心得了~,我们经常在程序中要实现显示当前有多少用户在线,以及在线用户的操作状态的功能,看了园子里朋友都有一些非常好的思路,这里我也提供一种很简单的方法: 1,用户登陆后,在每一 ...

  7. serv-u 用户使用sftp登录 时间显示不对_从无障碍思维出发,提升用户体验

    什么是无障碍思维?如何提升?具体如何使用?文章主要从这三点出发,对无障碍思维进行了梳理分析,与大家分享. 概念说明:一种不需要定制就能满足于各类需要用户群体的思维模式. 一.概述 无障碍这个概念被提出 ...

  8. 【Redis】Redis实现排行榜及相同积分按时间排序

    在日常的开发中,经常会碰到需要对用户的分值等进行排序,比如在游戏里面需要对战斗力进行排行,在组队活动中需要对各个队伍的贡献值进行排行,在微信中需要对各个好友的步数进行排行,此时一般会选择redis的有 ...

  9. 大剑无锋之SQL求用户最近的登录时间【面试推荐】

    表数据: 输出结果: 请用一条sql展示出来. 解题思路: 我们先用分组name看结果: select * from employees_plus group by name 结果: 发现展示的是以n ...

最新文章

  1. Java 8默认方法会破坏你的(用户的)代码
  2. 微软某程序员吐槽:如果毕业去字节,现在总包150万!如今一年才50万,看见字节的人都抬不起头!...
  3. OpenGL索引呈现
  4. cf1504. Travelling Salesman Problem
  5. wamp3.1.0下载地址
  6. 1007. 素数对猜想 (20)
  7. 计算机组成与体系结构之Flynn分类法
  8. ECharts地图省市县在对应地图的中心位置
  9. 利用windrose绘制风玫瑰图并解决错误问题
  10. 微信大数据:中国人怎么过国庆长假?
  11. uni-app 苹果登录
  12. treecnt 51Nod - 1677
  13. 教你如何用思维导图把一本书内容绘制成一张A4纸!
  14. 电源完整性PI原理知识1
  15. 一位新竹科学园区朋友的来信
  16. 长江大数据交易中心以数据安全标准护航安全和隐私
  17. Dell 工作站故障诊断报警信息原因查询
  18. 录音、上传、播放音频微信小程序实践
  19. 2018.7.3DAY1 李俊毅
  20. 一文读懂谷歌I/O 新硬件、Android Q及多项功能升级

热门文章

  1. trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)解析
  2. 多多自走棋改动_《多多自走棋》9月底最新平衡性改了什么 最新平衡性改动介绍...
  3. 浅谈JS转换字符串为数字
  4. 9.16nbsp;瑞晟软件笔试
  5. python文件下载
  6. 深度学习 - 记忆网络
  7. 问:用宏定义一年有多少秒(忽略闰年)
  8. 立创EDA助力2021全国电赛数百万奖学金!
  9. Matlab中实现圆形矩阵,圆外为0
  10. MYSQL——MYSQL中常见的数据库引擎