我的项目有个显示用户的遗忘曲线,需要统计在线用户以计算他们的曲线
思考了两种方案,但都是用redis的bitmap数据结构
bitmap是一种特殊类型的数组,其中每个元素只能存储0或1。在redis中,bitmap实际上是字符串,每个字符的每一位都被视为一个独立的位,因此一个字符串可以存储多达8*字符串长度的位。 这段代码中,markuseractive方法接收一个用户id作为参数。然后,它创建一个键,该键由字符串"active_users:"和当前日期组成,格式为iso_date。这样,每天都会有一个新的键,用于存储当天活跃的用户。 然后,它使用redisutils.setbit方法将用户id对应的位设置为1。这里,用户id被用作位的索引。例如,如果用户id为10,那么第10位将被设置为1。 这样,我们就可以通过检查特定位的值来确定用户是否活跃。如果位的值为1,那么用户就是活跃的;如果位的值为0,那么用户就是不活跃的。 这种方法的优点是,它可以在非常小的空间内存储大量的信息。此外,由于redis是内存数据库,因此这种方法的速度非常快。
方案一
- 使用心跳包来追踪和统计用户活跃状态,客户端每隔30分钟或者一段时间给服务端发送一个心跳,服务端获取到用户id然后存储到redis
- 但这样的话客户端要定时任务,且依赖客户端。
方案二
- 在用户每次请求操作的时候,由于我后端配置了shiro的拦截器判断每次请求是否token过期,加入标记用户活跃的逻辑,并redis设置过期时间2小时
- 缺点是资源消耗大,每次请求都要标记
@override public void markuseractive(int userid) { string key = "active_users:" + localdatetime.now().format(datetimeformatter.iso_local_date_time); redisutils.setbit(key, userid, true); // 设置2小时的过期时间 redisutils.expire(key, 2, timeunit.hours); }
markuseractive(int userid) 方法: 这个方法用于标记一个用户为活跃状态。它接收一个用户id作为参数。方法首先构造一个键,键的格式是 “active_users:” 加上当前的日期和时间。然后,它在 redis 数据库中将这个键对应的位(由用户id指定)设置为 true,表示该用户是活跃的。最后,它设置这个键的过期时间为2小时。这意味着,如果2小时内没有再次标记该用户为活跃,那么这个键就会从 redis 数据库中删除。
@override public list<integer> getactiveuserids() { list<integer> activeuserids = new arraylist<>(); // 当前时间 localdatetime currenttime = localdatetime.now(); for (int i = 0; i < 2; i++) { // 遍历过去2小时内的键 string key = "active_users:" + currenttime.minushours(i).format(datetimeformatter.iso_local_date_time); if (redisutils.haskey(key)) { // 遍历1000个用户 for (int j = 0; j < 1000; j++) { boolean isuseractive = redisutils.getbit(key, j); if (isuseractive != null && isuseractive) { activeuserids.add(j); } } } } return activeuserids; }
但是之后测试的时候发现在查找活跃用户的时候并没有找到,可能是时间戳精度问题,所以修改代码将其key保留到分钟形式
string key = "active_users:" + localdatetime.now().truncatedto(chronounit.minutes).format(datetimeformatter.iso_local_date_time);
到此这篇关于springboot项目redis统计在线用户的实现示例的文章就介绍到这了,更多相关springboot redis统计在线用户内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论