Skip to content

使用Redis的有序集合(zset)实现在线人数统计

核心方法是这四个:

zadd、zrangeByScore、zremrangeByScore、zrem

代码实现

application.yml

yaml
spring:
  redis:
    # 连接的那个数据库
    database: 0
    # redis服务的ip地址
    host: 127.0.0.1
    # redis端口号
    port: 6379
    # redis的密码,没设置过密码,可为空
    password:
java
@Data
public class VisitorDTO {
    private String visitorId;
}
java

@RestController
public class IndexController {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 添加在线用户
     * @param visitorDTO
     */
    @PostMapping("/visitor")
    @ResponseBody
    public void visitor(@RequestBody VisitorDTO visitorDTO) {
        LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(30);
        long timestamp = localDateTime.toEpochSecond(ZoneOffset.UTC);
        redisTemplate.opsForZSet().add("user.active", visitorDTO.getVisitorId(), timestamp);
    }

    /**
     * 查询在线人数
     * @return
     */
    @PostMapping("/getVisitor")
    @ResponseBody
    public Set<String> getVisitor() {

        LocalDateTime localDateTime = LocalDateTime.now();
        long minTimestamp = localDateTime.toEpochSecond(ZoneOffset.UTC);
        long maxTimestamp = localDateTime.plusSeconds(60).toEpochSecond(ZoneOffset.UTC);
        Set<String> strings = redisTemplate.opsForZSet().rangeByScore("user.active", minTimestamp, maxTimestamp);

        return strings;
    }

    /**
     * 清除在线用户
     * @param visitorDTO
     */
    @PostMapping("/logout")
    @ResponseBody
    public void logout(@RequestBody VisitorDTO visitorDTO) {
        redisTemplate.opsForZSet().remove("user.active", visitorDTO.getVisitorId());
    }
}
java
@Configuration
@EnableScheduling
@Slf4j
public class ScheduleConfiguration {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 定时清除离线用户
     * 间隔20秒执行一次
     */
    @Scheduled(fixedDelay = 1000 * 20)
    public void removeOffLineUser(){
        log.info("removeOffLineUser");
        LocalDateTime localDateTime = LocalDateTime.now();
        long maxTimestamp = localDateTime.toEpochSecond(ZoneOffset.UTC);

        redisTemplate.opsForZSet().removeRangeByScore("user.active", 0, maxTimestamp);
    }
}

参考:如何优雅的实现在线人数统计功能?