【Redis从头学-8】Redis中的ZSet数据类型实战场景之用户积分榜

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 【Redis从头学-8】Redis中的ZSet数据类型实战场景之用户积分榜

🌟前言


之前的篇章对Redis的String、List、Hash、Set数据类型已经做出了具体分析,并举例说明了其具体的实战场景。本文就结合Zset数据类型结构的特性,一起探讨其实战中的应用场景,并以积分榜功能为例来展示Zset数据类型的特点。


🌟ZSet数据类型分析


Redis中的ZSet(有序集合)数据类型是一种有序且不重复的集合,它在Set的基础上增加了一个分数(score)字段,用于对集合中的元素进行排序。下面对Redis ZSet数据类型进行一些分析:


  1. 有序性:ZSet中的元素按照其分数进行排序,使得元素在集合中有序存储。每个元素都有一个唯一的分数,可用于根据指定顺序进行范围查询或排序。
  2. 元素的唯一性:和Set一样,ZSet保证其中的元素都是唯一的,不会存在重复的元素。
  3. 高效的添加、删除和更新操作:ZSet提供了O(log N)时间复杂度的添加、删除和更新元素的操作。其中N为ZSet中元素的数量。这归功于Redis内部使用了跳表(Skip List)和哈希表两种结构实现ZSet。
  4. 支持范围查询和排名操作:ZSet支持根据分数范围进行查询,并可以按照分数大小对元素进行排名。通过排名操作,可以获取元素的排名以及根据排名返回一定范围的元素。


🌟ZSet类型实战应用场景


ZSet常用于需要根据分数进行排序的场景,例如排行榜、计分系统、有序任务队列等。它能够快速获取按照分数排序的元素,并且支持动态更新分数。


总而言之,Redis的ZSet数据类型提供了有序、唯一且高效的集合操作。它在排行榜、计分系统以及需要有序处理任务队列等场景中非常有用。通过对元素进行分数的设置和操作,可以灵活地满足各种实时数据排序和查询的需求。


用户积分榜功能


代码示例

我们使用了Spring Data Redis提供的RedisTemplate来操作Redis的ZSet。通过@Resource注解将RedisTemplate注入到LeaderboardService类中。


在LeaderboardService中,我们定义很多的功能方法来实现用户积分榜的功能,如添加用户积分、增加用户积分、获取用户排名、获取用户积分、获取排名靠前的用户列表以及获取积分在指定范围内的用户列表。


@Component
public class LeaderboardService {
    private static final String LEADERBOARD_KEY = "leaderboard";
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 添加用户积分
     *
     * @param user  用户名
     * @param score 积分
     */
    public void addScore(String user, double score) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        zSetOperations.add(LEADERBOARD_KEY, user, score);
    }
    /**
     * 增加用户积分
     *
     * @param user  用户名
     * @param score 积分增加量
     */
    public void incrementScore(String user, double score) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        zSetOperations.incrementScore(LEADERBOARD_KEY, user, score);
    }
    /**
     * 获取用户排名(从高到低)
     *
     * @param user 用户名
     * @return 用户的排名,如果用户不存在,则返回null
     */
    public Long getUserRank(String user) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        return zSetOperations.reverseRank(LEADERBOARD_KEY, user);
    }
    /**
     * 获取用户积分
     *
     * @param user 用户名
     * @return 用户的积分,如果用户不存在,则返回null
     */
    public Double getUserScore(String user) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        return zSetOperations.score(LEADERBOARD_KEY, user);
    }
    /**
     * 获取排名靠前的用户列表
     *
     * @param count 列表数量
     * @return 排名靠前的用户列表
     */
    public Set<String> getTopUsers(int count) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Set<String> topUsers = zSetOperations.reverseRange(LEADERBOARD_KEY, 0, count - 1);
        return topUsers;
    }
    /**
     * 获取积分在指定范围内的用户列表
     *
     * @param minScore 最低积分
     * @param maxScore 最高积分
     * @return 积分在指定范围内的用户列表
     */
    public Set<String> getUsersInRange(double minScore, double maxScore) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Set<String> usersInRange = zSetOperations.rangeByScore(LEADERBOARD_KEY, minScore, maxScore);
        return usersInRange;
    }
    /**
     * 获取积分在指定范围内的用户列表,并返回用户及其对应的积分信息
     *
     * @param minScore 最低积分
     * @param maxScore 最高积分
     * @return 包含用户及其对应积分的用户列表
     */
    public Set<String> getUsersWithScoresInRange(double minScore, double maxScore) {
        ZSetOperations<String, String> zSetOperations = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<String>> usersWithScoresInRange = zSetOperations
                .rangeByScoreWithScores(LEADERBOARD_KEY, minScore, maxScore);
        // 将TypedTuple转换为只包含用户的Set
        Set<String> usersSet = usersWithScoresInRange.stream()
                .map(ZSetOperations.TypedTuple::getValue)
                .collect(Collectors.toSet());
        return usersSet;
    }
}


数据测试

使用了 Spring Boot 框架来启动应用程序,并通过上下文获取 LeaderboardService 类的实例。然后,我们按照需求调用 LeaderboardService 类中的方法。


@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        LeaderboardService leaderboardService = context.getBean(LeaderboardService.class);
        // 添加用户积分
        leaderboardService.addScore("User1", 100);
        leaderboardService.addScore("User2", 200);
        leaderboardService.addScore("User3", 300);
        leaderboardService.addScore("User4", 400);
        leaderboardService.addScore("User5", 500);
        // 增加用户积分
        leaderboardService.incrementScore("User1", 50);
        leaderboardService.incrementScore("User3", 150);
        // 获取用户排名
        Long user1Rank = leaderboardService.getUserRank("User1");
        System.out.println("User1 Rank: " + user1Rank);
        // 获取用户积分
        Double user3Score = leaderboardService.getUserScore("User3");
        System.out.println("User3 Score: " + user3Score);
        // 获取排名靠前的用户列表
        Set<String> topUsers = leaderboardService.getTopUsers(3);
        System.out.println("Top Users: " + topUsers);
        // 获取积分在指定范围内的用户列表
        Set<String> usersInRange = leaderboardService.getUsersInRange(200, 400);
        System.out.println("Users in Range: " + usersInRange);
        // 获取积分在指定范围内的用户列表,并返回用户及其对应的积分信息
        Set<String> usersWithScoresInRange = leaderboardService.getUsersWithScoresInRange(200, 400);
        System.out.println("Users with Scores in Range: " + usersWithScoresInRange);
    }
}


运行结果

User1 Rank: 4

User3 Score: 450.0

Top Users: [User5, User4, User3]

Users in Range: [User4, User3, User2]

Users with Scores in Range: [User4, User3]


🌟写在最后


有关于Redis中的ZSet数据类型实战应用场景到此就结束了。功能演示代码的逻辑简单,目的是理解ZSet数据类型的应用,实际场景的逻辑根据具体需求而定。感谢大家的阅读,希望大家在评论区对此部分内容散发讨论或者有什么其他场景也可以在评论区提出。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
29天前
|
存储 消息中间件 NoSQL
Redis数据类型详解:选择合适的数据结构优化你的应用
Redis数据类型详解:选择合适的数据结构优化你的应用
|
2天前
|
消息中间件 监控 NoSQL
【亮剑】实战:Redis高负载排查记录
【4月更文挑战第30天】本文介绍了如何排查和解决Redis高负载问题。通过监控CPU、内存、网络IO和命令处理速度,可识别性能瓶颈。排查包括:分析慢查询、内存使用、网络连接和命令执行。优化措施涉及优化查询、减少复杂命令、使用连接池、调整数据结构等。建立监控系统、定期性能测试和持续优化是关键。
|
6天前
|
存储 缓存 NoSQL
node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)
node实战——koa给邮件发送验证码并缓存到redis服务(node后端储备知识)
13 0
|
7天前
|
存储 缓存 NoSQL
Redis入门到通关之Redis缓存数据实战
Redis入门到通关之Redis缓存数据实战
16 0
|
7天前
|
存储 SQL NoSQL
Redis入门到通关之五大基本数据类型及其使用场景
Redis入门到通关之五大基本数据类型及其使用场景
12 0
|
8天前
|
存储 NoSQL Redis
第十八章 Redis查看配置文件和数据类型
第十八章 Redis查看配置文件和数据类型
15 0
|
1月前
|
存储 XML NoSQL
Redis支持哪些数据类型?
Redis提供五种数据类型:String(支持JSON、XML等序列化,最大512MB),Hash(键值对,适合存储对象),List(有序列表,可在两端添加元素),Set(无序唯一元素集合),以及Sorted Set(有序集合,元素带分数排序)。每种类型有特定应用场景,优化了数据操作效率。
8 0
|
2月前
|
NoSQL Redis
Netty实战:模拟Redis的客户端
Netty实战:模拟Redis的客户端
14 0
|
2月前
|
存储 NoSQL Redis
KubeSphere 核心实战之二【在kubesphere平台上部署redis】(实操篇 2/4)
KubeSphere 核心实战之二【在kubesphere平台上部署redis】(实操篇 2/4)
27 0
|
2月前
|
存储 消息中间件 NoSQL
Redis 常见数据类型(对象类型)和应用案列
接下来,让我们走进 Redis 的对象世界,Redis 5.0版本就已经支持了下面的 9 种类型,分别是 :字符串对象、列表对象、哈希对象、集合对象、有序集合对象、Bitmaps 对象、HyperLogLog 对象、Geospatial 对象、Stream对象。
Redis 常见数据类型(对象类型)和应用案列