使用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);
}
}