基于redis的zset实现排行榜

devtools/2024/9/22 14:46:59/

文章目录

  • 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)
    • 🌟 亮点功能
    • 📦 spring cloud模块概览
      • 常用工具
    • 🔗 更多信息
    • 1.sun-club-subject集成redis
        • 1.sun-club-domain引入依赖
        • 2.sun-club-domain引入redis的工具类
          • 1.RedisConfig.java
          • 2.RedisUtil.java
        • 3.在application.yml下集成redis(是在spring下的)
    • 2.SubjectInfoDomainServiceImpl.java 修改逻辑
        • 1.依赖注入
        • 2.每添加一个题目都会计入排行榜
        • 3.getContributeList方法
    • 3.测试

🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)

Sun Frame Banner

轻松高效的现代化开发体验

Sun Frame 是我个人开源的一款基于 SpringBoot 的轻量级框架,专为中小型企业设计。它提供了一种快速、简单且易于扩展的开发方式。

我们的开发文档记录了整个项目从0到1的任何细节,实属不易,请给我们一个Star!🌟
您的支持是我们持续改进的动力。

🌟 亮点功能

  • 组件化开发:灵活选择,简化流程。
  • 高性能:通过异步日志和 Redis 缓存提升性能。
  • 易扩展:支持多种数据库和消息队列。

📦 spring cloud模块概览

  • Nacos 服务:高效的服务注册与发现。
  • Feign 远程调用:简化服务间通信。
  • 强大网关:路由与限流。

常用工具

  • 日志管理:异步处理与链路追踪。
  • Redis 集成:支持分布式锁与缓存。
  • Swagger 文档:便捷的 API 入口。
  • 测试支持:SpringBoot-Test 集成。
  • EasyCode:自定义EasyCode模板引擎,一键生成CRUD。

🔗 更多信息

  • 开源地址:Gitee Sun Frame
  • 详细文档:语雀文档
    在这里插入图片描述

1.sun-club-subject集成redis

1.sun-club-domain引入依赖
<!-- redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.4.2</version>
</dependency>
<!-- redis的pool -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.9.0</version>
</dependency>
<!-- jackson序列化 -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.12.7</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.7</version>
</dependency>
2.sun-club-domain引入redis的工具类
1.RedisConfig.java
package com.sunxiansheng.subject.domain.redis;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** Description: 原生 redis 的 template 的序列化器会产生乱码问题,重写改为 jackson* @Author sun* @Create 2024/6/5 14:16* @Version 1.0*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(redisSerializer);redisTemplate.setHashKeySerializer(redisSerializer);redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());return redisTemplate;}private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);jsonRedisSerializer.setObjectMapper(objectMapper);return jsonRedisSerializer;}}
2.RedisUtil.java
package com.sunxiansheng.subject.domain.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** Description: RedisUtil工具类* @Author sun* @Create 2024/6/5 14:17* @Version 1.0*/
@Component
@Slf4j
public class RedisUtil {@Resourceprivate RedisTemplate redisTemplate;private static final String CACHE_KEY_SEPARATOR = ".";/*** 构建缓存key* @param strObjs* @return*/public String buildKey(String... strObjs) {return Stream.of(strObjs).collect(Collectors.joining(CACHE_KEY_SEPARATOR));}/*** 是否存在key* @param key* @return*/public boolean exist(String key) {return redisTemplate.hasKey(key);}/*** 删除key* @param key* @return*/public boolean del(String key) {return redisTemplate.delete(key);}public void set(String key, String value) {redisTemplate.opsForValue().set(key, value);}public boolean setNx(String key, String value, Long time, TimeUnit timeUnit) {return redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit);}public String get(String key) {return (String) redisTemplate.opsForValue().get(key);}public Boolean zAdd(String key, String value, Long score) {return redisTemplate.opsForZSet().add(key, value, Double.valueOf(String.valueOf(score)));}public Long countZset(String key) {return redisTemplate.opsForZSet().size(key);}public Set<String> rangeZset(String key, long start, long end) {return redisTemplate.opsForZSet().range(key, start, end);}public Long removeZset(String key, Object value) {return redisTemplate.opsForZSet().remove(key, value);}public void removeZsetList(String key, Set<String> value) {value.stream().forEach((val) -> redisTemplate.opsForZSet().remove(key, val));}public Double score(String key, Object value) {return redisTemplate.opsForZSet().score(key, value);}public Set<String> rangeByScore(String key, long start, long end) {return redisTemplate.opsForZSet().rangeByScore(key, Double.valueOf(String.valueOf(start)), Double.valueOf(String.valueOf(end)));}/*** 可以使用这个来实现排行榜,指定键就相当于指定了一个排行榜,再指定成员和分数,则会给排行榜中的这个成员加分数* @param key zset的键* @param obj 成员,一般为用户的唯一标识* @param score 分数* @return*/public Object addScore(String key, Object obj, double score) {return redisTemplate.opsForZSet().incrementScore(key, obj, score);}public Object rank(String key, Object obj) {return redisTemplate.opsForZSet().rank(key, obj);}/*** 从 Redis 有序集合(Sorted Set)中按分数范围获取成员及其分数* @param key 排行榜的key* @param start 起始位置(包含)* @param end 结束位置(包含)* @return Set<ZSetOperations.TypedTuple<String>> : 每个 TypedTuple 对象包含以下内容:value: 集合中的成员,score: 成员的分数。*/public Set<ZSetOperations.TypedTuple<String>> rankWithScore(String key, long start, long end) {Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);return set;}}
3.在application.yml下集成redis(是在spring下的)
#  redis
redis:password:  # Redis服务器密码database: 0 # 默认数据库为0号timeout: 10000ms # 连接超时时间是10000毫秒lettuce:pool:max-active: 8 # 最大活跃连接数,使用负值表示没有限制,最佳配置为核数*2max-wait: 10000ms # 最大等待时间,单位为毫秒,使用负值表示没有限制,这里设置为10秒max-idle: 200 # 最大空闲连接数min-idle: 5 # 最小空闲连接数cluster:nodes:

2.SubjectInfoDomainServiceImpl.java 修改逻辑

1.依赖注入

image-20240622135949832

2.每添加一个题目都会计入排行榜

image-20240622140006091

3.getContributeList方法
@Override
public List<SubjectInfoBO> getContributeList() {// 从redis中得到排行榜信息Set<ZSetOperations.TypedTuple<String>> typedTuples = redisUtil.rankWithScore(RANK_KEY, 0, 5);// 打日志if (log.isInfoEnabled()) {log.info("SubjectInfoDomainServiceImpl getContributeList typedTuples:{}", typedTuples);}// 判空if (CollectionUtils.isEmpty(typedTuples)) {return Collections.emptyList();}// 如果查到了,就封装到BO中List<SubjectInfoBO> boList = new LinkedList<>();typedTuples.forEach(rank -> {SubjectInfoBO subjectInfoBO = new SubjectInfoBO();// 从redis中获取每个用户的题目数量和用户的loginIdString loginId = rank.getValue();int subjectCount = rank.getScore().intValue();// 设置题目数量subjectInfoBO.setSubjectCount(subjectCount);// rpc调用根据loginId来查询该用户的昵称和头像UserInfo userInfo = userRpc.getUserInfo(loginId);subjectInfoBO.setCreateUser(userInfo.getNickName());subjectInfoBO.setCreateUserAvatar(userInfo.getAvater());boList.add(subjectInfoBO);});return boList;
}

3.测试

1.登录后新增题目

image-20240622140115746

2.获取排行榜

image-20240622140133407


http://www.ppmy.cn/devtools/93779.html

相关文章

vue2 API-实例property在项目中的使用

1.$options 概念&#xff1a;用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处&#xff1a; 用处示例&#xff1a; ①获取&#xff0c;调用data外定义的属性 <script> export default {data() {return {};},//在data外面定义的属性和方法…

Python酷库之旅-第三方库Pandas(077)

目录 一、用法精讲 316、pandas.Series.str.findall方法 316-1、语法 316-2、参数 316-3、功能 316-4、返回值 316-5、说明 316-6、用法 316-6-1、数据准备 316-6-2、代码示例 316-6-3、结果输出 317、pandas.Series.str.fullmatch方法 317-1、语法 317-2、参数 …

【Linux】MySQL安装教程

Linux中MySQL安装教程 Step1&#xff1a;卸载系统自带的mysqlStep2&#xff1a;下载mysql8安装包Step3&#xff1a;上传mysql压缩包到 /opt 然后解压Step4&#xff1a;解压后按照如下顺序安装Step5&#xff1a;对mysql进行初始化Step6&#xff1a;修改mysql安装目录的所有用户和…

使用Anaconda安装多个版本的Python并与Pycharm进行对接

1、参考链接 Anaconda安装使用教程解决多Python版本问题_anaconda安装多个python版本-CSDN博客 基于上面的一篇博客的提示&#xff0c;我做了尝试。并在Pycharm的对接上做了拓展。 2、首先安装Anaconda 这个比较简单&#xff0c;直接安装即可&#xff1a; 3、设置conda.exe的…

NPM包管理高级技巧:使用版本范围测试锁定

引言 在JavaScript项目开发中&#xff0c;依赖管理是保证项目稳定性和可维护性的关键环节。NPM&#xff08;Node Package Manager&#xff09;作为Node.js的包管理器&#xff0c;提供了一套灵活的版本控制机制&#xff0c;允许开发者精确控制依赖包的版本。版本范围测试锁定是…

腾讯开源VITA!全方位对标GPT4o,全能多模态交互大模型!

腾讯优图实验室联合南京大学、厦门大学和中国科学院自动化研究所推出了VITA&#xff0c;一个开源的多模态大型语言模型。该模型擅长同时处理和分析视频、图像、文本和音频模态&#xff0c;并通过非唤醒交互和音频中断交互实现先进的多模态交互体验。 作者表示&#xff1a;所有训…

SQL Server端口设置完整详细步骤

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; 前面是对SQLserver服务器一些介绍&#xff0c;不想了解的可直接点击目录跳入正题&#xff0c;谢谢&#xff01;&#xff01;&#xff01; SQL Server 是由微软公司开发的关系数据库管理系统 (RDBMS)。它主要…

Linux Vim教程

Linux Vim 教程 Vim&#xff08;Vi IMproved&#xff09;是一个强大的文本编辑器&#xff0c;广泛用于编程和系统管理。本文将带你全面了解 Vim 的基础使用、常用命令、高级功能等。 1. 安装 Vim 在大多数 Linux 发行版中&#xff0c;Vim 已经预装。如果没有&#xff0c;可以…