🚀手把手教你用Redis实现百万级数据排行榜功能!(附完整Java实战)
在如今电商、游戏、社交类系统中,“排行榜”已成为不可或缺的功能之一。如何做到高性能、高并发、可扩展的排行榜?Redis + Java 是你的不二之选!
本文将带你从0到1实现百万级数据排行榜功能,不仅有原理讲解,还有完整Java代码实现!
📌一、为什么选择 Redis 实现排行榜?
Redis 提供了一个完美契合排行榜需求的数据结构:Sorted Set(有序集合)。
特点:
- 元素唯一,每个元素关联一个
score
- 自动按
score
排序(从小到大/从大到小) - 支持范围查询、排名查询、分数更新
适用于如:游戏积分榜、电商销售榜、粉丝活跃榜……
🧠二、排行榜基本功能设计
我们以“用户积分排行榜”为例,模拟百万用户数据,支持以下功能:
- 批量缓存百万用户数据
- 查询某个用户的当前排名
- 查询某个排名区间的用户列表(如TOP10)
- 实时更新用户分数并自动重新排序
🛠️三、Java + Redis 实战:百万数据排行榜
1️⃣ 技术栈选型
- Spring Boot
- Redis(建议 Redis 6.0+)
- Jedis / Lettuce(推荐使用 Lettuce)
- Java 8+
2️⃣ Maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
3️⃣ Redis 配置(application.yml)
spring:
data:
redis:
host: localhost
port: 6379
client-name: redisClient
timeout: 3000ms
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
4️⃣ 核心 Java 代码
🔹定义排行榜服务
@Service
public class RankService {
private static final String RANK_KEY = "user:score:rank";
@Autowired
private StringRedisTemplate redisTemplate;
public void addOrUpdateUserScore(String userId, double score) {
redisTemplate.opsForZSet().add(RANK_KEY, userId, score);
}
public Long getUserRank(String userId) {
Long rank = redisTemplate.opsForZSet().reverseRank(RANK_KEY, userId);
return rank != null ? rank + 1 : null;
}
public Set<ZSetOperations.TypedTuple<String>> getTopUsers(int start, int end) {
return redisTemplate.opsForZSet().reverseRangeWithScores(RANK_KEY, start, end);
}
public void generateTestData(int count) {
Random random = new Random();
Map<String, Double> dataMap = new HashMap<>();
for (int i = 1; i <= count; i++) {
dataMap.put("user_" + i, random.nextDouble() * 10000);
}
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
dataMap.forEach((userId, score) ->
((StringRedisConnection) connection).zAdd(RANK_KEY, score, userId)
);
return null;
});
}
public void clearRank() {
redisTemplate.delete(RANK_KEY);
}
}
5️⃣ 控制器测试接口
@RestController
@RequestMapping("/rank")
public class RankController {
@Autowired
private RankService rankService;
@PostMapping("/init")
public String initData(@RequestParam int count) {
rankService.clearRank();
rankService.generateTestData(count);
return "初始化" + count + "条数据成功";
}
@PostMapping("/update")
public String updateScore(@RequestParam String userId, @RequestParam double score) {
rankService.addOrUpdateUserScore(userId, score);
return "更新成功";
}
@GetMapping("/rank")
public String getRank(@RequestParam String userId) {
Long rank = rankService.getUserRank(userId);
return rank == null ? "未上榜" : "当前排名:" + rank;
}
@GetMapping("/top")
public List<String> getTop(@RequestParam int start, @RequestParam int end) {
Set<ZSetOperations.TypedTuple<String>> topUsers = rankService.getTopUsers(start, end);
return topUsers.stream()
.map(t -> t.getValue() + "(积分:" + String.format("%.2f", t.getScore()) + ")")
.collect(Collectors.toList());
}
}
📊四、百万数据实测表现
功能 | 响应时间(本地Redis) |
---|---|
初始化百万数据 | 4~6 秒 |
查询TOP10 | < 10 毫秒 |
查询某用户排名 | < 10 毫秒 |
更新用户积分 | < 10 毫秒 |
👉 说明:Redis SortedSet 结构支持 O(logN) 的插入和查询,适合高频查询/更新的排行榜场景。
🧩五、进阶优化建议
- ✅ 使用 pipeline 提升批量写入性能
- ✅ 使用 zremrangebyrank 控制数据容量(如限制前10万名)
- ✅ 使用 缓存用户详细信息(如昵称、头像) 降低多次查询开销
- ✅ 若数据超过千万级,可考虑分片或使用 Redis Cluster
✅六、总结回顾
能力 | Redis SortedSet |
---|---|
排名查询 | 支持 reverseRank |
分数更新 | add + 覆盖 |
分页查询 | reverseRange |
实时同步 | 支持自动排序 |
只需短短几百行代码,就能打造一个高性能、高并发的排行榜系统!
🔚最后:你可以这样用
📌 文章代码可用于:
- 游戏积分排行
- 电商销售榜
- 社交点赞榜
- 学习平台积分榜…
🎁 完整代码工程支持导入。关注公众号:程序猿小吴,留言即可打包下载!
如果你觉得文章对你有帮助,欢迎点赞、收藏、转发支持一下!❤️
📢 关注我,每周分享一篇高质量Java架构实战!