找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1757

积分

0

好友

263

主题
发表于 4 天前 | 查看: 14| 回复: 0

在线人数统计是Web应用中常见的需求,用于实时反映网站的活跃用户数量。实现这一功能有多种方式,本文将介绍一种基于Redis有序集合(ZSet)的经典实现方案,其核心依赖于四个关键命令:zaddzrangeByScorezremrangeByScorezrem

图片

实现步骤

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

识别用户是否在线主要取决于网站类型:

  • 需要登录的网站:通常根据用户的身份令牌(Token)是否有效来判断。
  • 公开的、无需登录的网站:则需要创建一套规则来识别独立访客。常见方式有IP地址、设备ID(DeviceId)或浏览器指纹。其中,浏览器指纹是更推荐的方案。

浏览器指纹通过组合多项信息来生成一个相对唯一的访客标识,包括:用户代理字符串(User-Agent)、HTTP请求头、屏幕分辨率、时区、语言设置、浏览器插件列表等。我们可以使用现成的JavaScript库(如FingerprintJS)来简化采集和生成过程。

示例代码如下:

// 安装:npm install @fingerprintjs/fingerprintjs
// 使用示例:
import FingerprintJS from '@fingerprintjs/fingerprintjs';

// 初始化指纹JS库
FingerprintJS.load().then(fp => {
  // 获取访客ID
  fp.get().then(result => {
    const visitorId = result.visitorId;
    console.log(visitorId);
  });
});

获取到唯一ID后,可将其置于Cookie或请求头中传递给后端,后端便可根据此ID标识用户。

2. ZADD命令:添加在线用户

ZADD命令用于向有序集合中添加成员,并为其指定一个分数(Score)。其基本语法为:ZADD key score member

在线人数统计场景中,我们可以将用户令牌(或浏览器指纹ID)作为member,将其过期时间的时间戳作为score。每次用户活动(如登录、访问)时,都执行一次添加操作。

// expireTimeout为用户令牌的过期时长(秒)
LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expireTimeout);
String expireTimeStr = DateUtil.formatFullTime(expireTime);
// 将用户token添加到名为"user.active"的有序集合中,分数为过期时间戳
redisService.zadd("user.active", Double.parseDouble(expireTimeStr), userToken);

此方案的巧妙之处在于,如果同一用户重复登录,新的记录会以更新的分数(过期时间)覆盖旧记录,从而保证集合中每个用户只保留最新的在线状态。

3. ZRANGEBYSCORE命令:查询在线人数

ZRANGEBYSCORE命令用于获取有序集合中分数在指定区间内的所有成员。语法为:ZRANGEBYSCORE key min max

要查询当前所有在线用户,只需查询分数大于等于当前时间戳的成员即可。

// 获取当前时间戳
String now = DateUtil.formatFullTime(LocalDateTime.now());
// 查询分数在[now, +inf]区间的所有用户
Set<String> userOnlineStringSet = redisService.zrangeByScore("user.active", now, "+inf");

userOnlineStringSet的大小即为当前的在线人数

4. ZREMRANGEBYSCORE命令:定时清理过期用户

有序集合不会自动删除过期的成员,因此需要一个定时任务来清理。ZREMRANGEBYSCORE命令可以删除分数在指定区间内的所有成员。语法为:ZREMRANGEBYSCORE key min max

定时任务可以定期执行以下逻辑,清理已过期的用户记录:

// 获取当前时间戳
String now = DateUtil.formatFullTime(LocalDateTime.now());
// 删除分数在[-inf, now)区间(即已过期)的所有用户
redisService.zremrangeByScore("user.active", "-inf", now);

这个操作是保障数据准确性的关键,防止已离线用户仍被计入统计。此类定时清理任务正是后端服务中常见的维护操作。

5. ZREM命令:用户主动退出时删除

当用户主动退出登录时,应立即将其从在线集合中移除。ZREM命令用于删除指定的一个或多个成员。语法为:ZREM key member [member ...]

// 用户退出时,直接删除其对应的token记录
redisService.zrem("user.active", userToken);

这样可以确保用户体验的一致性,即主动退出后立即从在线名单中消失。

小结

本方案的核心思路是:创建一个以“在线用户集合”为Key的Redis有序集合,以用户标识为Member,以其会话的过期时间戳为Score。通过ZADD记录或刷新用户在线状态,通过ZRANGEBYSCORE查询在线用户列表,通过ZREMRANGEBYSCORE定时清理过期数据,通过ZREM处理主动退出。方案逻辑清晰,利用Redis有序集合的特性高效实现了在线人数统计功能,在多种业务场景下都具备良好的实用性和扩展性。




上一篇:USB-C充电线选购指南:详解功率规格与Mac充电慢的根源
下一篇:云原生入门指南:微服务治理、容器化编排与可观测性核心组件解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 23:12 , Processed in 0.265667 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表