SpringBoot运用Redis统计用户在线数量的两种方法实现

 更新时间:2025年06月25日 09:36:19   作者:weixin_43833540  
本文主要介绍了SpringBoot运用Redis统计用户在线数量的两种方法实现,包括通过RedisSet精确记录用户状态,或用RedisBitmap按位存储优化内存,Set适合小规模场景,Bitmap适用于大规模连续ID,可根据需求选择实现方式

在Spring Boot里运用Redis统计用户在线数量。

项目依赖与配置

1. 引入依赖

首先,在pom.xml文件中添加Spring Data Redis依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 配置Redis连接

application.properties中进行Redis连接的配置:

spring.redis.host=localhost
spring.redis.port=6379

方案1:借助Redis Set实现精确统计

1. 创建Redis操作Service

编写一个Redis操作Service,用于处理用户在线状态:

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Set;

@Service
public class OnlineUserService {

    private static final String ONLINE_USERS_KEY = "online_users";

    private final RedisTemplate<String, String> redisTemplate;

    public OnlineUserService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // 用户登录
    public void login(String userId) {
        redisTemplate.opsForSet().add(ONLINE_USERS_KEY, userId);
    }

    // 用户退出
    public void logout(String userId) {
        redisTemplate.opsForSet().remove(ONLINE_USERS_KEY, userId);
    }

    // 获取在线用户数
    public Long getOnlineCount() {
        return redisTemplate.opsForSet().size(ONLINE_USERS_KEY);
    }

    // 获取所有在线用户ID
    public Set<String> getOnlineUsers() {
        return redisTemplate.opsForSet().members(ONLINE_USERS_KEY);
    }
}

2. 控制器示例

创建一个控制器,用于测试上述功能:

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/online")
public class OnlineUserController {

    private final OnlineUserService onlineUserService;

    public OnlineUserController(OnlineUserService onlineUserService) {
        this.onlineUserService = onlineUserService;
    }

    @PostMapping("/login/{userId}")
    public String login(@PathVariable String userId) {
        onlineUserService.login(userId);
        return userId + " 已登录";
    }

    @PostMapping("/logout/{userId}")
    public String logout(@PathVariable String userId) {
        onlineUserService.logout(userId);
        return userId + " 已退出";
    }

    @GetMapping("/count")
    public Long getCount() {
        return onlineUserService.getOnlineCount();
    }

    @GetMapping("/users")
    public Set<String> getUsers() {
        return onlineUserService.getOnlineUsers();
    }
}

方案2:使用Redis Bitmap实现按位存储

1. Bitmap操作Service

创建一个专门用于Bitmap操作的Service:

import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class OnlineUserBitmapService {

    private static final String ONLINE_USERS_BITMAP_KEY = "online_users_bitmap";

    private final RedisTemplate<String, Object> redisTemplate;

    public OnlineUserBitmapService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // 用户登录(userId需为Long类型)
    public void login(Long userId) {
        redisTemplate.execute((RedisCallback<Boolean>) connection ->
                connection.setBit(ONLINE_USERS_BITMAP_KEY.getBytes(), userId, true));
    }

    // 用户退出
    public void logout(Long userId) {
        redisTemplate.execute((RedisCallback<Boolean>) connection ->
                connection.setBit(ONLINE_USERS_BITMAP_KEY.getBytes(), userId, false));
    }

    // 检查用户是否在线
    public Boolean isOnline(Long userId) {
        return redisTemplate.execute((RedisCallback<Boolean>) connection ->
                connection.getBit(ONLINE_USERS_BITMAP_KEY.getBytes(), userId));
    }

    // 获取在线用户数
    public Long getOnlineCount() {
        return redisTemplate.execute((RedisCallback<Long>) connection ->
                connection.bitCount(ONLINE_USERS_BITMAP_KEY.getBytes()));
    }

    // 统计指定范围内的在线用户数
    public Long getOnlineCount(long start, long end) {
        return redisTemplate.execute((RedisCallback<Long>) connection ->
                connection.bitCount(ONLINE_USERS_BITMAP_KEY.getBytes(), start, end));
    }
}

2. 控制器示例

创建对应的控制器:

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/online/bitmap")
public class OnlineUserBitmapController {

    private final OnlineUserBitmapService onlineUserBitmapService;

    public OnlineUserBitmapController(OnlineUserBitmapService onlineUserBitmapService) {
        this.onlineUserBitmapService = onlineUserBitmapService;
    }

    @PostMapping("/login/{userId}")
    public String login(@PathVariable Long userId) {
        onlineUserBitmapService.login(userId);
        return userId + " 已登录";
    }

    @PostMapping("/logout/{userId}")
    public String logout(@PathVariable Long userId) {
        onlineUserBitmapService.logout(userId);
        return userId + " 已退出";
    }

    @GetMapping("/count")
    public Long getCount() {
        return onlineUserBitmapService.getOnlineCount();
    }

    @GetMapping("/{userId}")
    public Boolean isOnline(@PathVariable Long userId) {
        return onlineUserBitmapService.isOnline(userId);
    }
}

使用建议

1. Set方案的适用场景

  • 当需要精确统计在线用户数量,并且能够获取在线用户列表时,可以使用Set方案。
  • 适合用户规模在百万级别以下的情况,因为Set会存储每个用户的ID。

2. Bitmap方案的适用场景

  • 若用户ID是连续的整数(或者可以映射为连续整数),Bitmap方案会更节省内存。
  • 对于大规模用户(比如亿级)的在线统计,Bitmap方案具有明显优势。
  • 示例中使用Long类型的userId,在实际应用中,你可能需要一个ID映射器,将业务ID转换为连续的整数。

到此这篇关于SpringBoot运用Redis统计用户在线数量的两种方法实现的文章就介绍到这了,更多相关Spring Boot Redis统计用户在线内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot使用CXF集成WebService的方法

    SpringBoot使用CXF集成WebService的方法

    这篇文章主要介绍了SpringBoot使用CXF集成WebService的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Java动态编译执行代码示例

    Java动态编译执行代码示例

    这篇文章主要介绍了Java动态编译执行代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Mybatis入门教程之新增、更新、删除功能

    Mybatis入门教程之新增、更新、删除功能

    这篇文章给大家介绍了Mybatis进行基本的增删改操作,非常不错,具有参考借鉴价值,需要的的朋友参考下
    2017-02-02
  • Java子线程无法获取Attributes的解决方法(最新推荐)

    Java子线程无法获取Attributes的解决方法(最新推荐)

    在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决方案,对Java子线程无法获取Attributes的解决方案感兴趣的朋友一起看看吧
    2025-01-01
  • 编写Java代码对HDFS进行增删改查操作代码实例

    编写Java代码对HDFS进行增删改查操作代码实例

    这篇文章主要介绍了Java代码对HDFS进行增删改查操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • Java查搜索文件内容实现方式

    Java查搜索文件内容实现方式

    用户为解决无法搜索文件内容的问题,编写了一个支持单文件、文件夹及多层递归查找的工具,具备字符串匹配及忽略大小写功能,并计划扩展日期、创建人等组合搜索条件,最终打包成exe便于快速查找所有文件内容
    2025-09-09
  • Java NIO.2 使用Path接口来监听文件、文件夹变化

    Java NIO.2 使用Path接口来监听文件、文件夹变化

    Java7对NIO进行了大的改进,新增了许多功能,接下来通过本文给大家介绍Java NIO.2 使用Path接口来监听文件、文件夹变化 ,需要的朋友可以参考下
    2019-05-05
  • Java实现PNG图片格式转BMP图片格式

    Java实现PNG图片格式转BMP图片格式

    在实际开发中,有时需要在不同平台、不同应用场景中对图片格式进行转换,本文主要介绍了如何使用 Java 语言实现将 PNG 格式的图片转换为 BMP 格式的图片,需要的可以了解下
    2025-03-03
  • Java中2个对象字段值比较是否相同

    Java中2个对象字段值比较是否相同

    本文主要介绍了Java中2个对象字段值比较是否相同,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Java 超详细讲解数据结构中的堆的应用

    Java 超详细讲解数据结构中的堆的应用

    堆首先是一个完全二叉树,堆分为小根堆和大根堆。小根堆,所有结点的左右子节点都不小于根节点;大根堆,所有结点的左右子节点都不大于根节点。优先级队列(priorityQueue)底层就是一个小根堆
    2022-04-04

最新评论