在线人数统计功能怎么实现?

一、前言

大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

在线人数统计这个功能相信大家一眼就明白是啥,这个功能不难做,实现的方式也很多,这里说一下我常使用的方式:使用Redis的有序集合(zset)实现。
核心方法是这四个:zaddzrangeByScorezremrangeByScorezrem

二、实现步骤

1. 如何认定用户是否在线?

认定用户在线的条件一般跟网站有关,如果网站需要登录才能进入,那么这种网站就是根据用户的token令牌有效性判断是否在线;
如果网站是公开的,是那种不需要登录就可以浏览的,那么这种网站一般就需要自定一个规则来识别用户,也有很多方式实现如IPdeviceId浏览器指纹,推荐使用浏览器指纹的方式实现。

浏览器指纹可能包括以下信息的组合:用户代理字符串 (User-Agent string)、HTTP请求头信息、屏幕分辨率和颜色深度、时区和语言设置、浏览器插件详情等。现成的JavaScript库,像 FingerprintJSClientJS,可以帮助简化这个过程,因为它们已经实现了收集上述信息并生成唯一标识的算法。

使用起来也很简单,如下:

// 安装:npm install @fingerprintjs/fingerprintjs// 使用示例:
import FingerprintJS from '@fingerprintjs/fingerprintjs';// 初始化指纹JS Library
FingerprintJS.load().then(fp => {// 获取访客IDfp.get().then(result => {const visitorId = 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给用户令牌设置了一个过期时间
LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expireTimeout);
String expireTimeStr = 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)查询当前所有的在线用户

// 获取当前的日期
String now = 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)定时清除在线用户

// 获取当前的日期
String now = 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,然后对这个集合进行增删改查,实现起来还是比较巧妙和简单的,大家有兴趣可以试试看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/805267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于奇异值分解(Singular Value Decomposition,SVD)的信号去噪算法

01.基于奇异值分解(SVD)去噪原理 奇异值分解&#xff08;Singular Value Decomposition, SVD&#xff09;是线性代数中一种重要的矩阵分解方法&#xff0c;它可以用于信号处理、图像去噪、数据压缩等多种应用。在图像去噪的过程中&#xff0c;SVD可以用来分离图像中的信号和噪…

Transformer详解和知识点总结

目录 1. 注意力机制1.1 注意力评分函数1.2 多头注意力&#xff08;Multi-head self-attention&#xff09; 2. Layer norm3. 模型结构4. Attention在Transformer中三种形式的应用 论文&#xff1a;https://arxiv.org/abs/1706.03762 李沐B站视频&#xff1a;https://www.bilibi…

SpringBoot Starter子模块下无法生成spring-configuration-metadata.json文件

一.SpringBoot Starter的作用 Starter的机制极大的方便了业务系统接入相关能力&#xff0c;它有一个非常友好的能力就是引入starter后&#xff0c;在配置相关的配置项时&#xff0c;能自动提示&#xff0c;极大的提升了使用的友好度。 二.遇到的问题 我在为Juggle开发系统star…

CLI举例:上下行连接路由器(路由引流)

CLI举例&#xff1a;上下行连接路由器&#xff08;路由引流&#xff09; 介绍了集群设备&#xff0c;上下行连接路由器的配置举例。 组网需求 如图1所示&#xff0c;上行网络使用BGP&#xff0c;下行网络使用OSPF&#xff0c;多数据中心统一通过路由器R4接入Internet。 希望…

HarmonyOS 开发-多模态页面转场动效实现案例

介绍 本示例介绍多模态页面转场动效实现&#xff1a;通过半模态转场实现半模态登录界面&#xff0c;通过配置NavDestinationMode类型为DIALOG&#xff0c;实现半模态的背景为透明&#xff0c;再与全屏模态和组件转场结合实现多模态组合登录场景&#xff0c;其中手机验证码登录…

从零开始为香橙派orangepi zero 3移植主线linux——2.kernel + rootfs

从零开始为香橙派orangepi zero 3移植主线linux——2.kernel rootfs 参考文章&#xff1a;一、linux kernel移植二、根文件系统2.1 buildroot构建1.修改toolchain下的交叉编译链2.修改系统配置3.去除内置kernel和uboot编译4.添加rootfs.tar格式的输出 2.2 ubuntu-base移植 三、…

Linux gcc day4 权限

首先来看比如ls、pwd等究竟是什么呢&#xff1f; 那ls是如何在shell中执行起来的呢&#xff1f;shell命令又是什么呢&#xff1f; shell命令&#xff1a;命令行解释器&#xff1a;表现&#xff1a;你看到的命令行提示符&#xff0c;以及可以输入指令并且可以执行&#xff08;是…

贪心算法简介

目录 一、什么是贪心算法&#xff1f; 二、贪心算法的特点 三、贪心算法解决找零问题、最短路径问题、背包问题 1.找零问题 2.最短路径问题 3.背包问题 一、什么是贪心算法&#xff1f; 贪心算法就是希望通过局部最优来解决全局最优 基本步骤&#xff1a;1.将问题分为若…

【I/O】Unix IO 介绍

IO 模型&#xff08;一&#xff09; Unix IO 一个输入操作共包含两个阶段&#xff1a; 等待数据准备好从内核将数据复制到进程 对于一个套接字上的输入操作&#xff0c;通常第一步是等待数据从网络中到达&#xff0c;当数据到达时&#xff0c;先将数据复制到内核缓冲区中&a…

【UE 委托】如何利用函数指针理解委托的基本原理

目录 0 引言1 函数指针模拟多播委托 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&#x1f4a5; 标题&#xff1a;【UE 委托】如何利用函数指针理解委托的基本原理❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难…

js base64 img 转 file

打印canvas图像的dataurl const imgDataUrl canvas.toDataURL();console.log(imgDataUrl)上传的图像编码 1,把base64编码转为文件对象第一个参数dataUrl是一个base64的字符串。第二个参数是文件名可以随意命名funtion base64toFile(dataurl, filename file) {let arr datau…

Git 安装和配置

下载 Git 网址: https://git-scm.com/download 安装 Git 双击安装包, 开始安装. 修改安装路径, 选择非中文无空格路径: 开始安装: 安装成功: 配置 Git 安装完成后, 在任意文件夹内, 右键, 可以显示两个 Git 选项, 就说明安装成功了.

汇舟问卷:海外问卷调查适合哪些人群去参与?

大家好&#xff0c;我是汇舟问卷。关于海外问卷调查这个项目最近一直备受关注&#xff0c;那么这个项目究竟有哪些人群适合参与进来呢&#xff1f;我们一起来看看。 第一&#xff0c;海外问卷调查适合一些没有找到工作或者拥有充足业余时间的人。只要您拥有一台电脑和网络连接…

IDEA 解决 java: 找不到符号 符号: 类 __ (使用了lombok的注解)

原因IDEA版本太高&#xff0c;在 ProcessingEnvironement 预编译的时候是以代理的方式来执行的&#xff0c;不再是直接 javac方式, lombok依赖的 javac方式的 annotation processors 不再生效了 解决办法&#xff1a;下面这一句&#xff0c;加在下图中 -Djps.track.ap.depen…

关于帆软报表取OA选择框-下拉列表值的解决方案

问题&#xff1a;制度一览表每次在OA端增加或修改制度类别后&#xff0c;都要在帆软报表修改后才能正确显示。 原因分析&#xff1a;以前大家没有找到OA下拉列表的维护表&#xff0c;采用的是在帆软端通过内置数据集来解决&#xff0c;需要人工维护。 解决方案&#xff1a; …

Linux函数学习 epoll

1、Linux epoll函数 1.1、创建epoll实例 int epoll_create1(int flag); 返回值&#xff1a;-1 失败&#xff0c;非负数 成功 flag &#xff1a;默认传入0 1.2、管理epoll对象 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epfd &#xff1a;e…

rebase和merge的区别

合并分支用rebase还是merge&#xff1f; 实际开发工作的时候&#xff0c;我们都是在自己的分支开发&#xff0c;然后将自己的分合并到主分支&#xff0c;那合并分支用2种操作&#xff0c;这2种操作有什么区别呢&#xff1f; git上新建一个项目&#xff0c;默认是有master分支…

蓝桥杯物联网竞赛_STM32L071KBU6_我的全部省赛及历年模拟赛源码

我写的省赛及历年模拟赛代码 链接&#xff1a;https://pan.baidu.com/s/1A0N_VUl2YfrTX96g3E8TfQ?pwd9k6o 提取码&#xff1a;9k6o

YOLOv8模型剪枝实战:DepGraph(依赖图)方法

课程链接&#xff1a;YOLOv8模型剪枝实战&#xff1a;DepGraph(依赖图)方法_在线视频教程-CSDN程序员研修院 YOLOv8是一个当前非常流行的目标检测器&#xff0c;本课程使用DepGraph&#xff08;依赖图&#xff09;剪枝方法对YOLOv8进行网络剪枝&#xff0c;使其更加轻量和实用…

Android源码笔记-输入事件(二)

这一节主要了解输入事件的获取&#xff0c;InputReaderThread继承自C的Thread类&#xff0c;Thread类封装了pthread线程工具&#xff0c;提供了与Java层Thread类相似的API。C的Thread类提供了一个名为threadLoop()的纯虚函数&#xff0c;当线程开始运行后&#xff0c;将会在内建…