Site Overlay

基于Redis Zset实现在线用户统计

需求:

统计页面的当前在线用户统计。

由于不是socket连接,所以不是真实的实时在线用户,是对用户登录或者普通操作的时间进行标记时间戳,时间戳之后多少分钟内,都是算作在线的,限定时间之后就算作离线。

在我当前项目中我有一个统一的token验证方法,我就把标记时间戳的方法加在该方法中。

 /**
     * 在线用户统计
     * @param uid uid
     */
//用户在线时间戳
    private void onlineUser(int uid) {
        redisTemplate.opsForZSet().add("onlineUserCount", uid + "", ServerTimer.getDayHourMinute());
    }

    /**
     * 公共登陆验证
     *
     * @param name  用户名
     * @param token token
     * @return result
     */
    private String CommonLogin(String name, String token) {
        User user1 = userRedisDao.getOneByName(name);
        if (user1 == null) {
            return "用户" + name + "不存在";
        }
        User user = userRedisDao.getOneByToken(token);
        if (user == null) {
            return "登陆过期,请重新登陆";
        }
        if (user.getUid() != user1.getUid()) {
            return "已在其他设备登陆,请退出应用重新登陆";
        }
        this.onlineUser(user.getUid());
        return "success";
    }

这里的ServerTimer.getHourMinute()是将当前时间存为HHmm的一个int,作为时间戳存入“onlineUserCount”这个key的一个member的分数中,用于之后自动判断过期清除。

	//ServerTimer.getHourMinute()
	public static int getDayHourMinute() {
		String timeHm = ServerTimer.getTimeHm();
		return Integer.parseInt(timeHm);
	}
        public static String getTimedHm() {
		Calendar now = Calendar.getInstance();
		SimpleDateFormat s = new SimpleDateFormat("ddHHmm");
		return s.format(now.getTime());
	}

存入时间戳的步骤就到这里,之后我们还需要一个定时任务用于自动清除过期的member:

    //5分钟未操作清除用户在线统计
    @Scheduled(fixedDelay = 60000)
    public void clearOnlineUser() {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MINUTE,-5);
        SimpleDateFormat s = new SimpleDateFormat("ddHHmm");
        int score = Integer.parseInt(s.format(now.getTime()));
        Long count = redisTemplate.opsForZSet().removeRangeByScore("onlineUserCount", -1, score);
        log.info("当前在线用户:{}",count);
    }

查询方法:

    /**
     * 获取当前在线用户数
     *
     * @return 当前在线用户数
     */
    public Object getOnlineUser() {
        return redisTemplate.opsForZSet().count("onlineUserCount", -1, 999999);
    }

以上就是基于redis Zset在线用户的解决方案,相较于心跳,减少了与前端的交互,纯后端实现, 且内存占用性能占用均在可接受的范围内。

发表回复

您的电子邮箱地址不会被公开。

A beliving heart is your magic My heart
欢迎来到Diuut的个人博客,这里是我的一些零零碎碎的知识汇总,希望有能帮到你的内容。 | 蜀ICP备2021011635号-1 | Copyright © 2024 Diuut. All Rights Reserved.