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

 

前言

在日常开发中,我们有时候需要对在线用户进行管理,由于登录信息是可以过期的,那么使用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的关系集合中的元素。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值