在现代应用程序中,排行榜功能常用于展示用户或内容的排名,如游戏中的分数排名、社交平台上的活跃度排名等。Redis 提供的有序集合(Sorted Set)结构,能够通过分数进行排序,非常适合用来构建排行榜。本文将介绍如何使用 Spring Boot 3 和 Redis 实现一个简单的排行榜功能。
1. 为什么选择 Redis 来实现排行榜?
Redis 的有序集合(Sorted Set)具备以下优点:
- 高效排序:有序集合是通过分数(Score)来进行排序的,支持快速的插入、删除和排序操作。
- 高性能:Redis 是内存数据库,读写速度非常快,特别适合实时性要求高的应用。
- 丰富的操作:Redis 提供了多种操作命令,如按分数范围查询、获取前 N 名等,非常适合排行榜的需求。
Redis 有序集合通过 zadd
命令向集合中添加成员,并为每个成员设置一个分数。通过 zrange
等命令可以按分数从小到大或从大到小获取成员的排名。
2. 项目环境准备
2.1. 添加依赖
首先,在 pom.xml
中引入 Spring Boot 3 和 Redis 的相关依赖,具体参考重学SpringBoot3-集成Redis(一)之基本使用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.2. 配置 Redis 连接
在 application.yml
中配置 Redis:
spring:
data:
redis:
host: localhost
port: 6379 # Redis 端口
password: redis123456 # 如果有密码可以在这里配置
lettuce:
pool:
max-active: 100 # 最大并发连接数
max-idle: 50 # 最大空闲连接数
min-idle: 10 # 最小空闲连接数
3. 排行榜功能实现
3.1 排行榜服务的实现
我们使用 Redis 的有序集合(Sorted Set
)来存储排行榜的数据。成员(用户或内容)作为集合的元素,得分(如游戏分数、点赞数)作为排序依据。
package com.coderjia.boot310redis.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author CoderJia
* @create 2024/10/7 下午 09:13
* @Description
**/
@Service
public class LeaderboardService {
@Autowired
private StringRedisTemplate redisTemplate;
private static final String LEADERBOARD_KEY = "leaderboard";
// 添加用户及其得分到排行榜
public void addUserToLeaderboard(String userId, double score) {
redisTemplate.opsForZSet().add(LEADERBOARD_KEY, userId, score);
}
// 获取前N名用户
public Set<String> getTopUsers(int n) {
return redisTemplate.opsForZSet().reverseRange(LEADERBOARD_KEY, 0, n - 1);
}
// 获取某个用户的排名
public Long getUserRank(String userId) {
return redisTemplate.opsForZSet().reverseRank(LEADERBOARD_KEY, userId);
}
// 获取某个用户的得分
public Double getUserScore(String userId) {
return redisTemplate.opsForZSet().score(LEADERBOARD_KEY, userId);
}
// 获取用户的排名和得分
public Map<String, Object> getUserRankAndScore(String userId) {
Map<String, Object> result = new HashMap<>();
result.put("rank", getUserRank(userId));
result.put("score", getUserScore(userId));
return result;
}
}
3.2 排行榜功能的 REST 接口
为排行榜功能创建简单的 REST API,用户可以通过该接口添加分数、查看前几名和用户排名等操作。
package com.coderjia.boot310redis.demos.web;
import com.coderjia.boot310redis.service.LeaderboardService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.Set;
/**
* @author CoderJia
* @create 2024/10/10 下午 10:36
* @Description
**/
@RestController
@RequestMapping("/api/leaderboard")
public class LeaderboardController {
@Autowired
private LeaderboardService leaderboardService;
// 添加用户得分
@PostMapping("/add")
public ResponseEntity<String> addUser(@RequestParam("userId") String userId, @RequestParam("score") double score) {
leaderboardService.addUserToLeaderboard(userId, score);
return ResponseEntity.ok("User added to leaderboard.");
}
// 获取前N名
@GetMapping("/top")
public ResponseEntity<Set<String>> getTopUsers(@RequestParam("topN") int topN) {
return ResponseEntity.ok(leaderboardService.getTopUsers(topN));
}
// 获取某个用户的排名和得分
@GetMapping("/user/{userId}")
public ResponseEntity<Map<String, Object>> getUserRankAndScore(@PathVariable String userId) {
return ResponseEntity.ok(leaderboardService.getUserRankAndScore(userId));
}
}
3.3 测试接口
你可以使用 Postman 或 curl 来测试这些接口。例如,添加用户的接口请求可以这样发起:
curl -X POST "http://localhost:8080/api/leaderboard/add?userId=1&score=100"
获取前 5 名的接口请求:
curl -X GET "http://localhost:8080/api/leaderboard/top?topN=5"
获取某个用户的排名和得分:
curl -X GET "http://localhost:8080/api/leaderboard/user/1"
4. 关键代码解析
redisTemplate.opsForZSet().add(key, value, score)
:将用户 ID 和分数作为一对数据添加到有序集合中,key
为排行榜的键。redisTemplate.opsForZSet().reverseRange(key, start, end)
:根据分数从高到低获取排行榜前几名用户。redisTemplate.opsForZSet().reverseRank(key, value)
:获取用户的排名,返回值是排名(从 0 开始)。redisTemplate.opsForZSet().score(key, value)
:获取用户的分数。
5. 小结
使用 Spring Boot 3 与 Redis 实现排行榜非常高效且简便。Redis 的有序集合为我们提供了强大的排序功能,能够轻松处理各种排行榜需求。通过该方案,我们可以实现以下功能:
- 动态添加用户得分到排行榜
- 实时获取前几名的用户
- 查询用户的排名和分数
Redis 由于其快速的读写性能,非常适合用于实时性要求高的排行榜应用场景。如果你需要开发类似的功能,Redis 无疑是一个理想的选择。