使用 Redis 在 Spring Boot 中实现排行榜功能

news2024/10/10 12:19:26

一、Redis Sorted Set 简介

Redis 提供的 Sorted Set 数据结构非常适合用于排行榜场景。Sorted Set 既具备 Set 的无重复元素特性,又具备 List 的排序特性。Sorted Set 中的每个元素都会关联一个分数(score),通过这个分数进行排序。

1.1 Sorted Set 的基本操作

  • 添加元素ZADD key score member,将元素 member 及其对应的 score 添加到 key 对应的 Sorted Set 中。
  • 删除元素ZREM key member,从 key 对应的 Sorted Set 中移除 member 元素。
  • 查询元素排名ZRANK key member,返回 memberkey 对应的 Sorted Set 中的排名,排名从 0 开始。
  • 查询前 N 名ZRANGE key 0 N-1 WITHSCORES,返回前 N 名的元素及其分数。

1.2 Sorted Set 的优势

Redis 的 Sorted Set 采用的是跳跃表(Skip List)和哈希表(Hash Table)来实现。跳跃表能够提供快速的有序访问,哈希表提供了快速的元素查找能力。因此,Sorted Set 能够以 O(log N) 的时间复杂度进行数据的增删查改,适合高性能的排行榜需求。

二、Spring Boot 项目集成 Redis

在 Spring Boot 项目中,集成 Redis 十分简单。Spring 提供了强大的 Spring Data Redis,它对 Redis 进行了封装,让我们可以更方便地与 Redis 进行交互。

2.1 引入依赖

首先,在 pom.xml 文件中引入 Spring Data Redis 相关依赖:

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

2.2 配置 Redis 连接

application.yml 文件中配置 Redis 的连接信息:

spring:
  redis:
    host: localhost
    port: 6379
    timeout: 5000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

2.3 配置 RedisTemplate

为了方便操作 Redis,我们可以在配置类中配置 RedisTemplate

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 设置key和value的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        return template;
    }
}

三、使用 Redis 实现排行榜

3.1 设计排行榜操作接口

我们需要设计一个服务类,用于封装 Redis 的排行榜操作。接口类如下:

public interface LeaderboardService {
    void addScore(String userId, double score);
    void removeUser(String userId);
    Long getUserRank(String userId);
    Double getUserScore(String userId);
    Set<ZSetOperations.TypedTuple<Object>> getTopUsers(int topN);
}

3.2 实现排行榜功能

接下来,我们实现 LeaderboardService 接口。通过使用 RedisTemplateZSetOperations,可以方便地操作 Redis 中的 Sorted Set

@Service
public class LeaderboardServiceImpl implements LeaderboardService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String LEADERBOARD_KEY = "game:leaderboard";

    @Override
    public void addScore(String userId, double score) {
        redisTemplate.opsForZSet().add(LEADERBOARD_KEY, userId, score);
    }

    @Override
    public void removeUser(String userId) {
        redisTemplate.opsForZSet().remove(LEADERBOARD_KEY, userId);
    }

    @Override
    public Long getUserRank(String userId) {
        return redisTemplate.opsForZSet().rank(LEADERBOARD_KEY, userId);
    }

    @Override
    public Double getUserScore(String userId) {
        return redisTemplate.opsForZSet().score(LEADERBOARD_KEY, userId);
    }

    @Override
    public Set<ZSetOperations.TypedTuple<Object>> getTopUsers(int topN) {
        return redisTemplate.opsForZSet().reverseRangeWithScores(LEADERBOARD_KEY, 0, topN - 1);
    }
}

3.3 解释代码实现

  1. 添加分数:通过 ZSetOperations#add 方法将用户 ID 和分数加入排行榜。
  2. 删除用户:通过 ZSetOperations#remove 方法从排行榜中删除指定用户。
  3. 获取用户排名:通过 ZSetOperations#rank 方法获取用户在排行榜中的排名。注意,排名是从 0 开始的。
  4. 获取用户分数:通过 ZSetOperations#score 方法获取用户的当前分数。
  5. 获取前 N 名用户:通过 ZSetOperations#reverseRangeWithScores 方法,获取排行榜中前 N 名的用户及其分数。

四、Redis 排行榜常见问题与优化

4.1 数据量过大时的性能问题

尽管 Redis 的 Sorted Set 数据结构能够在 O(log N) 的时间复杂度下完成操作,但当排行榜的数据量非常大时,可能会面临内存占用和响应时间变长的问题。为了应对这种情况,可以采用以下优化手段:

  • 分页查询:如果需要获取较多排名用户的数据,可以采用分页查询的方式,避免一次性获取大量数据。

  • 定期清理低排名用户:如果应用场景中低排名用户不重要,可以定期清理排行榜中的低排名用户,减少数据量。

4.2 用户分数更新问题

在某些场景下,用户的分数可能会频繁变化,例如游戏中的实时分数更新。此时可以考虑以下两点:

  • 原子性操作:使用 Redis 的 ZINCRBY 命令,可以在排行榜中对用户的分数进行增量更新,确保分数更新的原子性。

  • 缓存策略:如果用户分数变化频率很高,可以考虑在 Redis 中设置缓存过期时间,以减少频繁更新的压力。

4.3 分布式环境下的排行榜一致性问题

在分布式环境中,多个服务器可能会同时对同一个排行榜进行操作,这可能会引发一致性问题。为了解决这种问题,可以:

  • 使用 Redis 集群:Redis 原生支持集群模式,可以通过水平扩展的方式来提升性能和一致性。
  • 锁机制:在某些需要强一致性的场景中,可以通过分布式锁机制(如 Redis 的 SETNX 命令)来保证数据一致性。

五、测试与验证

在开发完成后,我们需要编写一些简单的测试代码来验证排行榜功能是否正常。可以使用 Spring 的单元测试框架进行测试。

@SpringBootTest
public class LeaderboardServiceTests {

    @Autowired
    private LeaderboardService leaderboardService;

    @Test
    public void testAddScore() {
        leaderboardService.addScore("user1", 100);
        leaderboardService.addScore("user2", 150);
        leaderboardService.addScore("user3", 200);
    }

    @Test
    public void testGetUserRank() {
        Long rank = leaderboardService.getUserRank("user2");
        System.out.println("user2 rank: " + rank);
    }

    @Test
    public void testGetTopUsers() {
        Set<ZSetOperations.TypedTuple<Object>> topUsers = leaderboardService.getTopUsers(3);
        topUsers.forEach(user -> {
            System.out.println(user.getValue() + " - " + user.getScore());
        });
    }
}

六、总结

本文详细介绍了如何在 Spring Boot 中使用 Redis 实现排行榜功能。通过 Redis 的 SortedSet 数据结构,我们可以高效地实现增、删、查、改操作,并能够轻松应对大规模并发请求。通过合理的优化措施,可以进一步提升排行榜的性能与稳定性。希望本文能帮助你理解并应用 Redis 来构建高效的排行榜系统。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2201963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第461题汉明距离

题目&#xff1a; 题解&#xff1a; class Solution {public int hammingDistance(int x, int y) {int s x ^ y, ret 0;while (s ! 0) {s & s - 1;ret;}return ret;} }

线性ADRC(LADRC)系统算法框图

非线性ADRC(NLADRC)详细算法框图和源代码请参考专栏系列文章,常用链接如下: 1、NLADRC自抗扰控制 NLADRC自抗扰控制从Simulink仿真到PLC控制实现_自抗扰控制器 simulink仿真-CSDN博客文章浏览阅读1.6k次,点赞2次,收藏7次。本文介绍了如何将ADRC自抗扰控制算法从Simulink…

基于Renesas R7FA8D1BH (Cortex®-M85)自适应蓝牙控制智能小车

目录 概述 1 系统框架结构 2 系统硬件介绍 2.1 电机驱动控制结构 2.1.1 PWM控制小车接口介绍 2.1.2 小车运行方向控制原理 2.2 外围传感器接口 2.2.1 I2C接口设备 2.2.2 IO接口 2.2.3 UART接口 2.2.4 其他接口 2.3 障碍物监测接口 2.4 测速模块接口 3 系统软件架构…

你还在为找不到免费录屏工具而烦恼吗?

嘿&#xff0c;各位小伙伴们&#xff0c;今天咱们来聊聊录屏软件吧&#xff01;你是不是经常需要录制电脑屏幕&#xff0c;做做教程、游戏解说或者工作汇报呢&#xff1f;那你肯定得选个好用的录屏工具啊&#xff01;来来来&#xff0c;跟着我一起&#xff0c;我来给你们推荐几…

SpringBoot项目打成jar包,在其他项目中引用

1、首先新建一个SpringBoot工程 记得要将Gradle换成Maven 2、新建一个要引用的方法 3、打包的时候要注意&#xff1a; ① 不能使用springboot项目自带的打包插件进行打包&#xff0c;下面是自带的&#xff1a; ②要换成传统项目的maven打包&#xff0c;如下图&#xff1a; 依…

算法 动态规划

更多文章&#xff1a;https://www.pandaer.space 动态规划 算法很简单&#xff01;今天我们来聊聊动态规划&#xff0c;我们先从动态规划怎么来的讲起&#xff0c;然后聊聊动态规划应该如何学&#xff1f;最后正式开始动态规划的学习之旅。 动态规划怎么就出现了呢&#xff…

前端性能优化全面指南

前端性能优化是提升用户体验的关键&#xff0c;页面加载速度、响应时间和交互流畅度直接影响用户的留存率和满意度。以下是常用的前端性能优化方法&#xff0c;从网络层、资源加载、JavaScript 执行、渲染性能等方面进行全方位优化。 减少 HTTP 请求 合并文件&#xff1a;将多…

markdown里粘贴图片的同时保存路径 在vscode里实现

下载扩展Markdown Image 设置保存路径 参考链接 https://blog.cxplay.org/works/vscode-to-markdown-editor/#markdown-image

HDLBits中文版,标准参考答案 | 3.2.5 Finite State Machines | 有限状态机(2)

关注 望森FPGA 查看更多FPGA资讯 这是望森的第 17 期分享 作者 | 望森 来源 | 望森FPGA 目录 1 Lemmings 1 2 Lemmings 2 3 Lemmings 3 4 Lemmings 4 5 One-hot FSM | 独热 FSM 6 PS/2 packet parser | PS/2 数据包解析器 7 PS/2 packet parser anddatapath | PS/2 数…

55 WebSocket

55 WebSocket 参考资料 WebSocket SpringBoot使用WebSocket SpringBoot 集成WebSocket详解 前言 WebSocket是HTML5下一种新的协议&#xff08;websocket协议本质上是一个基于tcp的协议&#xff09;它实现了浏览器与服务器全双工通信&#xff0c;能更好的节省服务器资源和…

AI大模型微调产品经理面试必备全攻略,非常详细收藏我这一篇就够了

前言 这两天跟很多做程序员的朋友聊天&#xff0c;怎么看全网火爆的大模型。让我挺意外的是&#xff0c;大家的反馈普遍都很焦虑 。 在AI大模型微调领域的产品经理面试中&#xff0c;总会遇到一系列与技术细节、项目经验、市场趋势以及职业规划相关的问题。以下是一些建议的面…

RabbitMQ中如何解决消息堆积问题,如何保证消息有序性

RabbitMQ中如何解决消息堆积问题 如何保证消息有序性 只需要让一个消息队列只对应一个消费者即可

cdr激活码序列号coredraw2024安装包破解版coreldraw2024永久序列号最新

&#x1f31f;设计界的新宠儿来啦&#xff01;CorelDRAW 2024震撼登场&#x1f389; ### &#x1f308; 开篇狂想曲&#xff1a;设计师们的“瑞士军刀”升级记&#xff01;&#x1f3a8; 嘿&#xff0c;亲爱的创意达人们&#x1f44b;&#xff01;今天&#xff0c;就让我们共同…

6.将扩散模型与其他生成模型的关联(1)

在本章中&#xff0c;我们首先介绍其他5种重要的生成模型&#xff0c;包括变分自编码器抗网络、归一化流、自回归模型和基于能量的模型&#xff0c;分析它们的优点和局限性&#xff0c;并说明这些生成模型是如何通过纳入扩散模型而得到促进的。1 .变分自编码器与扩散模型 …

Java | Leetcode Java题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int m g.length, n s.length;int count 0;for (int i 0, j 0; i < m && j < n; i, j) {while (j < n &&…

鸿蒙开发之ArkUI 界面篇 二十五 点赞综合案例

要实现如下图效果&#xff0c;红框处是点赞数&#xff0c;点击会变色和数字增加1&#xff1a; 我们首先分析布局结构&#xff0c;整体式垂直方向的布局&#xff0c;外层容器自然是Colum&#xff0c;上层是图片组件Image&#xff0c;接下来是Text组件&#xff0c;接下来是Row组件…

Unity实战案例全解析 类宝可梦回合制的初级案例 源码分析(加了注释和流程图)

这是一个老教程了&#xff0c;但是对于没有写过回合制的初级程序同学来讲是比较适合的&#xff0c;也可以直接看源码&#xff0c;半小时内可以解决战斗 当然&#xff0c;我也没写过回合制系统所以就到处找&#xff0c;思路明白了就能自己修改了 视频教程 - 油管链接 Turn-Bas…

ComfyUI | 5分钟部署最新Flux大模型

Midjourney 和 Stable Diffusion 都是目前流行的 AI 图像生成工具&#xff0c;它们能够根据文本描述生成高质量的图像。都是基于深度学习技术的文本到图像生成模型&#xff0c;但它们各自基于不同的大模型。 但最近推出了一款比前两者更强大&#xff0c;生成图像更加逼真&…

UE4 材质学习笔记04(着色器性能优化)

一.着色器性能优化 1.衡量着色器的性能 衡量着色器性能的主要方法有三个 第一个&#xff1a;可以使用场景的视图模式的优化视图模式的着色器复杂度 下面的滑条代表了着色器指令的复杂度 如果场景大部分是绿色的&#xff0c;说明着色器耗能低&#xff0c;反之白色则是很糟糕…

VS Code安装以及配置

安装 1. 下载安装 VScode官网 注意&#xff0c;这一步最好全部打勾 2. 设置默认terminal为cmd 3. 修改Run Code的配置 参考&#xff1a; https://blog.csdn.net/weixin_46474921/article/details/132841711