包阅导读总结
1. 在线人数统计、Redis 有序集合、用户在线认定、浏览器指纹、定时清除
2. 本文介绍了使用 Redis 的有序集合实现在线人数统计的方法。先认定用户是否在线,公开网站推荐用浏览器指纹获取用户唯一 ID。通过 zadd 命令添加在线用户,zrangeByScore 命令查询在线人数,zremrangeByScore 命令定时清除下线用户,zrem 命令在用户退出登录时删除成员。
3.
– 在线人数统计功能实现
– 前言
– 作者身份及说明
– 实现步骤
– 认定用户是否在线
– 登录网站根据 token 令牌有效性
– 公开网站可用 IP、deviceId、浏览器指纹,推荐后者
– 可用 FingerprintJS 或 ClientJS 库获取用户唯一 ID
– zadd 命令添加在线用户
– 命令介绍及示例
– 为用户令牌设置过期时间,添加到有序集合
– zrangeByScore 命令查询在线人数
– 命令介绍及示例
– 根据当前日期查询在线用户集,其 size 即在线人数
– zremrangeByScore 命令定时清除在线用户
– 命令介绍及示例
– 写定时任务删除下线用户
– zrem 命令用户退出登录时删除成员
– 命令介绍及示例
– 确保主动退出用户下线
– 小结
– 方案核心逻辑总结
思维导图:
文章地址:https://mp.weixin.qq.com/s/dbpOykMBZeZYoCxYLIkxDQ
文章来源:mp.weixin.qq.com
作者:summo
发布时间:2024/7/10 2:34
语言:中文
总字数:1737字
预计阅读时间:7分钟
评分:84分
标签:Redis,在线人数统计,有序集合,浏览器指纹,JavaScript 库
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
一、前言
大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
在线人数统计这个功能相信大家一眼就明白是啥,这个功能不难做,实现的方式也很多,这里说一下我常使用的方式:使用Redis的有序集合(zset
)实现。核心方法是这四个:zadd
、zrangeByScore
、zremrangeByScore
、zrem
。
二、实现步骤
1. 如何认定用户是否在线?
认定用户在线的条件一般跟网站有关,如果网站需要登录才能进入,那么这种网站就是根据用户的token令牌有效性判断是否在线;如果网站是公开的,是那种不需要登录就可以浏览的,那么这种网站一般就需要自定一个规则来识别用户,也有很多方式实现如IP
、deviceId
、浏览器指纹
,推荐使用浏览器指纹
的方式实现。
浏览器指纹可能包括以下信息的组合:用户代理字符串 (User-Agent string)、HTTP请求头信息、屏幕分辨率和颜色深度、时区和语言设置、浏览器插件详情等。
现成的JavaScript库,像 FingerprintJS
或 ClientJS
,可以帮助简化这个过程,因为它们已经实现了收集上述信息并生成唯一标识的算法。
使用起来也很简单,如下:
//安装:npminstall@fingerprintjs/fingerprintjs
//使用示例:
importFingerprintJSfrom'@fingerprintjs/fingerprintjs';
//初始化指纹JSLibrary
FingerprintJS.load().then(fp=>{
//获取访客ID
fp.get().then(result=>{
constvisitorId=result.visitorId;
console.log(visitorId);
});
});
这样就可以获取一个访问公开网站的用户的唯一ID了,当用户访问网站的时候,将这个ID放到访问链接的Cookie或者header中传到后台,后端服务根据这个ID标示用户。
2. zadd命令添加在线用户
(1)zadd命令介绍zadd
命令有三个参数
key:有序集合的名称。score1、score2 等:分数值,可以是整数值或双精度浮点数。member1、member2 等:要添加到有序集合的成员。例子:
向名为 myzset 的有序集合中添加一个成员:ZADD myzset 1 "one"
(2)添加在线用户标识到有序集合中
//expireTime给用户令牌设置了一个过期时间
LocalDateTimeexpireTime=LocalDateTime.now().plusSeconds(expireTimeout);
StringexpireTimeStr=DateUtil.formatFullTime(expireTime);
//添加用户token到有序集合中
redisService.zadd("user.active",Double.parseDouble(expireTimeStr),userToken);
由于一个用户可能户会重复登录,这就导致userToken也会重复,但为了不重复计算这个用户的访问次数,
zadd
命令的第二个参数很好的解决了这个问题。我这里的逻辑是:每次添加一个在线用户时,利用当前时间加上过期时间计算出一个分数,可以有效保证当前用户只会存在一个最新的登录态。
3. zrangeByScore命令查询在线人数
(1)zrangeByScore命令介绍
key:指定的有序集合的名字。min 和 max:定义了查询的分数范围,也可以是 -inf 和 +inf(分别表示“负无穷大”和“正无穷大”)。例子:
查询分数在 1 到 3之间的所有成员:ZRANGEBYSCORE myzset 1 3
(2)查询当前所有的在线用户
//获取当前的日期
Stringnow=DateUtil.formatFullTime(LocalDateTime.now());
//查询当前日期到"+inf"之间所有的用户
Set<String>userOnlineStringSet=redisService.zrangeByScore("user.active",now,"+inf");
利用zrangeByScore方法可以查询这个有序集合指定范围内的用户,这个
userOnlineStringSet
也就是在线用户集,它的size就是在线人数了。
4. zremrangeByScore命令定时清除在线用户
(1)zremrangeByScore命令介绍
key:指定的有序集合的名字。min 和 max:定义了查询的分数范围,也可以是 -inf 和 +inf(分别表示“负无穷大”和“正无穷大”)。例子:
删除分数在 1 到 3之间的所有成员:ZREMRANGEBYSCORE myzset 1 3
(2)定时清除在线用户
//获取当前的日期
Stringnow=DateUtil.formatFullTime(LocalDateTime.now());
//清除当前日期到"-inf"之间所有的用户
redisService.zremrangeByScore(""user.active"","-inf",now);
由于有序集合不会自动清理下线的用户,所以这里我们需要写一个定时任务去定时删除下线的用户。
5. zrem命令用户退出登录时删除成员
(1)zrem命令介绍
key:指定的有序集合的名字。members:需要删除的成员例子:
删除名为xxx的成员:ZREM myzset "xxx"
(2)定时清除在线用户
//删除名为xxx的成员
redisService.zrem("user.active","xxx");
删除 zset中的记录,确保主动退出的用户下线。
三、小结一下
这种方案的核心逻辑就是,创建一个在线用户身份集合
为key,利用用户身份
为member,利用过期时间
为score,然后对这个集合进行增删改查,实现起来还是比较巧妙和简单的,大家有兴趣可以试试看。