【Redis从头学-8】Redis中的ZSet数据类型实战场景之用户积分榜
🧑💻作者名称:DaenCode
🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。
😎人生感悟:尝尽人生百味,方知世间冷暖。
📖所属专栏:Redis从头学

文章目录
- 🌟前言
- 🌟ZSet数据类型分析
- 🌟ZSet类型实战应用场景
- 用户积分榜功能
- 代码示例
- 数据测试
- 运行结果
- 🌟写在最后
🌟前言
之前的篇章对Redis的String、List、Hash、Set数据类型已经做出了具体分析,并举例说明了其具体的实战场景。本文就结合Zset数据类型结构的特性,一起探讨其实战中的应用场景,并以积分榜功能为例来展示Zset数据类型的特点。
🌟ZSet数据类型分析
Redis中的ZSet(有序集合)数据类型是一种有序且不重复的集合,它在Set的基础上增加了一个分数(score)字段,用于对集合中的元素进行排序。下面对Redis ZSet数据类型进行一些分析:
- 有序性:ZSet中的元素按照其分数进行排序,使得元素在集合中有序存储。每个元素都有一个唯一的分数,可用于根据指定顺序进行范围查询或排序。
- 元素的唯一性:和Set一样,ZSet保证其中的元素都是唯一的,不会存在重复的元素。
- 高效的添加、删除和更新操作:ZSet提供了O(log N)时间复杂度的添加、删除和更新元素的操作。其中N为ZSet中元素的数量。这归功于Redis内部使用了跳表(Skip List)和哈希表两种结构实现ZSet。
- 支持范围查询和排名操作: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";@Resourceprivate 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转换为只包含用户的SetSet<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从头学-8】Redis中的ZSet数据类型实战场景之用户积分榜
🧑💻作者名称:DaenCode 🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。 😎人生感悟:尝尽人生百味,方知世间冷暖。 📖所属专栏:Re…...
Springboot内嵌SQLite配置使用
版本号 MacOS Apple M1 | Jdk17 | Maven 3.8.5 | SpringBoot 2.6.9 | SQLite 3.42.0.0 pom.xml <dependencies><dependency><groupId>org.xerial</groupId><artifactId>sqlite-jdbc</artifactId><version>3.42.0.0</version&g…...
【微服务学习笔记】认识微服务
【微服务学习笔记】认识微服务 单体架构 分布式架构 微服务架构 SpringCloud 服务拆分和注意事项 服务拆分的案例demo 各个服务之间的数据库都是相互独立的,你不能直接访问对方的数据库,只能从一个服务像另外一个服务发起远程调用 在订单模块的服务中 …...
基于Android R快速编译recovery-ramdisk.img
Android默认没有单编recovery-ramdisk.img的命令,我们可以自己修改Makefile实现 修改:build/core/Makefile 添加: .PHONY: recovery-ramdisk-nodeps recovery-ramdisk-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)echo "make …...
Redis分布式缓存
分布式缓存 -- 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题: 1.Redis持久化 Redis有两种持久化方案: RDB持久化 AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file(Redis数据备份文件)&#x…...
最大公约数和最小公倍数
最大公约数: 概念: 公约数中最大的称为最大公约数。 对任意的若干个正整数,1总是它们的公因数。 公约数与公倍数相反,就是既是A的约数同时也是B的约数的数,12和15的公约数有1,3,最大公约数就是…...
数据结构——二叉搜索树(附带C++实现版本)
文章目录 二叉搜索树概念 二叉树的实际应用二叉树模拟实现存储结构二叉搜索树构成二叉搜索树的查找插入操作中序遍历二叉树的删除循环(利用左子树最右节点)递归(利用右子树根节点) 二叉树拷贝二叉树资源的销毁 二叉树实现完整代码总结 二叉搜索树 概念 二叉搜索树…...
C++(3)C++对C的扩展Extension
类型增强 1、类型更加严格 不初始化,无法通过编译;C不初始化,则随机赋值 #include <iostream> #include <stdlib.h>int main() {const int a 100; //真正的const,无法修改 // int *p &a; 报错const int *p…...
在vscode(idea)使用GitHub账号、Copilot异常
在idea使用GitHub账号、Copilot异常 登录GitHub显示 Invalid authentication data.Connection refused: connect或者副驾驶显示 Failed to initiate the GitHub login process. Please try again.一般网上的方法推荐使用token登录,或者降级副驾驶 经过研究&#x…...
新的后端渲染:服务器驱动UI
通过API发送UI是一种彻底的新方法,将改变传统的UI开发。 一项正在改变我们对用户界面 (UI) 的看法的技术是通过 API 发送 UI,也称为服务器驱动UI。这种方法提供了新水平的活力和灵活性,正在改变 UI 开发的传统范例。 服务器驱动 UI 不仅仅是…...
Postman如何做接口自动化测试?
前言 什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试,模拟人去操作软件界面,把人从简单重复的劳动中解放出来。 本质是用代码去测试另一段代码,属于一种软件开发工作,已经开发完…...
excel文本函数篇2
本期主要介绍LEN、FIND、SEARCH以及后面加B的情况: (1)后缀没有B:一个字节代表一个中文字符 (2)后缀有B:两个字节代表一个中文字符 1、LEN(text):返回文本字符串中的字符个数 2、…...
【MyBatis】动态SQL > 重点:${...}和#{...}与resultMap和resultType的区别
目录 一、MyBatis动态sql 1.1 动态sql的作用 1.2 动态sql作用论证 1.2.1 条件判断:<if> 1.2.2 循环迭代:<foreach> 1.2.3 SQL片段重用 1.2.4 动态条件组合:<choose><when><otherwise> 1.2.5 <where…...
什么是BEM命名规范?为什么要使用BEM命名规范?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ BEM命名规范⭐ 为什么使用BEM命名规范?⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为…...
JavaScript:交集和差集的应用场景
在集合A和集合B中,属于集合A,同时也属于集合B的元素组成的集合,就是交集。 在A中所有不属于集合B元素,组合成集合,就是差集。 那么在平时的开发中,如何使用差集和交集来解决问题呢? 现在有这…...
达梦数据库表空间创建和管理
概述 本文将介绍在达梦数据库如何创建和管理表空间。 1.创建表空间 1.1表空间个数限制 理论上最多允许有65535个表空间,但用户允许创建的表空间 ID 取值范围为0~32767, 超过 32767 的只允许系统使用,ID 由系统自动分配,ID不能…...
三、MySQL 数据库安装集
一、CentOS—YUM 1. MySQL—卸载 # 1、查看存在的MySQL。 rpm -qa | grep -i mysql rpm -qa | grep mysql# 2、删除存在的MySQL。 rpm -e –-nodeps 包名# 3、查找存在的MySQL目录。 find / -name mysql# 4、删除存在的MySQL目录。 rm -rf 目录# 5、删除存在的MySQL配置文件。…...
【BASH】回顾与知识点梳理(三十九)
【BASH】回顾与知识点梳理 三十九 三十九. make、tarball、函数库及软件校验39.1 用 make 进行宏编译为什么要用 makemakefile 的基本语法与变量 39.2 Tarball 的管理与建议使用原始码管理软件所需要的基础软件Tarball 安装的基本步骤一般 Tarball 软件安装的建议事项 (如何移除…...
蓝蓝设计-UI设计公司案例-HMI列车监控系统界面设计解决方案
2013年,为加拿大庞巴迪(Bombardier)设计列车监控系统界面设计。 2015-至今,为中车集团旗下若干公司提供HMI列车监控系统界面设计,综合考虑中车特点、城轨车、动车组的不同需求以及HMI硬键屏和触摸 屏的不同操作方式,重构框架设计、交互设计、…...
Blazor前后端框架Known-V1.2.13
V1.2.13 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 Gitee: https://gitee.com/known/KnownGithub:https://github.com/known/Known 概述 基于C#和Blazo…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
