使用Spring Boot实现Redis多数据库缓存

Redis多数据库存储实现用户行为缓存

在我的系统中,为了优化用户行为数据的存储与访问效率,我引入了Redis缓存,并将数据分布在不同的Redis数据库中。通过这种方式,可以减少单一数据库的负载,提高系统的整体性能。

主要实现步骤
  1. Redis配置

    • 配置两个Redis连接工厂,分别用于存储Token和用户行为数据。
    • 创建对应的RedisTemplate实例,指定不同的连接工厂及序列化方式。
  2. 用户行为服务

    • 通过UserBehaviorService接口及其实现类UserBehaviorServiceImpl,实现对用户点赞、收藏、评论、浏览行为的记录。
    • 在操作数据库的同时,将用户行为数据存储到Redis中以提高读取效率。
  3. Token拦截器

    • 使用TokenInterceptor类在每次请求前验证Token。
    • 验证通过后,将用户信息存储到ThreadLocal中,供后续操作使用。
代码实现
Redis配置类
@Configuration
public class RedisConfig {@Value("${spring.data.redis.host}")private String redisHost;@Value("${spring.data.redis.port}")private int redisPort;@Value("${spring.data.redis.password}")private String redisPassword;@Bean(name = "tokenRedisConnectionFactory")public RedisConnectionFactory tokenRedisConnectionFactory() {RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);config.setPassword(redisPassword);config.setDatabase(0);return new LettuceConnectionFactory(config);}@Bean(name = "userBehaviorRedisConnectionFactory")public RedisConnectionFactory userBehaviorRedisConnectionFactory() {RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);config.setPassword(redisPassword);config.setDatabase(1);return new LettuceConnectionFactory(config);}@Bean(name = "redisTemplate")public StringRedisTemplate redisTemplate(@Qualifier("tokenRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());return template;}@Bean(name = "userBehaviorRedisTemplate")public RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate(@Qualifier("userBehaviorRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Map<String, Integer>> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class));return template;}
}
用户行为服务实现类
@Service
public class UserBehaviorServiceImpl implements UserBehaviorService {private static final long CACHE_EXPIRATION_DAYS = 1;private static final String CACHE_PREFIX = "articleCounts:";@Autowiredprivate UserBehaviorMapper userBehaviorMapper;@Autowired@Qualifier("userBehaviorRedisTemplate")private RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate;@Overridepublic void setLikeArticle(Likes likes) {likes.setCreateTime(LocalDateTime.now());Integer userId = ThreadLocalUtil.getUser("id");if (userId != null) {likes.setUserId(userId);}userBehaviorMapper.insertLike(likes);}@Overridepublic void setFavoriteArticle(Favorites favorites) {favorites.setCreateTime(LocalDateTime.now());Integer userId = ThreadLocalUtil.getUser("id");if (userId != null) {favorites.setUserId(userId);}userBehaviorMapper.insertFavorite(favorites);}@Overridepublic void setCommentArticle(Comments comments) {comments.setCreateTime(LocalDateTime.now());Integer userId = ThreadLocalUtil.getUser("id");if (userId != null) {comments.setUserId(userId);}userBehaviorMapper.insertComment(comments);}@Overridepublic void setViewArticle(Views views) {views.setCreateTime(LocalDateTime.now());Integer userId = ThreadLocalUtil.getUser("id");if (userId != null) {views.setUserId(userId);}userBehaviorMapper.insertView(views);}@Overridepublic Map<String, Integer> getArticleCounts(Integer articleId) {String key = CACHE_PREFIX + articleId;Map<String, Integer> counts = userBehaviorRedisTemplate.opsForValue().get(key);if (counts == null) {counts = fetchArticleCountsFromDB(articleId);cacheArticleCounts(articleId, counts);}return counts;}private Map<String, Integer> fetchArticleCountsFromDB(Integer articleId) {Map<String, Integer> counts = new HashMap<>();counts.put("likesCount", userBehaviorMapper.selectLikesCount(articleId));counts.put("favoritesCount", userBehaviorMapper.selectFavoritesCount(articleId));counts.put("commentsCount", userBehaviorMapper.selectCommentsCount(articleId));counts.put("viewsCount", userBehaviorMapper.selectViewsCount(articleId));return counts;}private void cacheArticleCounts(Integer articleId, Map<String, Integer> counts) {String key = CACHE_PREFIX + articleId;userBehaviorRedisTemplate.opsForValue().set(key, counts, CACHE_EXPIRATION_DAYS, TimeUnit.DAYS);}
}
Token拦截器
@Component
public class TokenInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {String token = request.getHeader("Authorization");if (token == null || token.isEmpty()) {response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}try {ValueOperations<String, String> operations = redisTemplate.opsForValue();String redisToken = operations.get(token);if (redisToken == null) {response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}Map<String, Object> claims = JwtUtil.parseToken(token);ThreadLocalUtil.setUser(claims);return true;} catch (Exception e) {response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}}@Overridepublic void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {ThreadLocalUtil.remove();}
}

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

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

相关文章

GEE案例——利用MODIS数据(NDVI)计算中国大陆2000-2023年的MK、Sens趋势性分析和Z值统计以及方差分析

简介 利用MODIS数据(NDVI)计算2000-2023年中国大陆的MK、Sens趋势性分析和Z值统计以及方差分析 流程 要进行NDVI数据的趋势性分析和统计分析,需要按照以下步骤进行: 1. 数据准备:获取2000-2023年的MODIS NDVI数据,可以从NASA的MODIS数据网站或其他可靠的数据来源获取…

yarn保姆级安装和使用

目录 前言 一、yarn简介 主要特性 使用场景 二、yarn的安装 yarn的下载 配置环境变量 三、yarn的常用命令 四、yarn的常用配置项 五、npm与yarn的区别 前言 本文旨在介绍如何安装和使用Yarn&#xff0c;以及它的一些常见用法。我们将从Yarn的基本概念开始&#xff0c;…

使用try-with-resources语句替代try-finally语句

Java类库中包含许多必须通过调用close方法手动关闭的资源&#xff0c;例如InputStream、OutputStream和java.sql.Connection。 开发人员经常忽视关闭资源&#xff0c;其性能结果可想而知。 从以往来看&#xff0c;try-finally语句是保证资源正确关闭的最佳方式&#xff0c;即使…

Web前端的规划:深度解构与未来展望

Web前端的规划&#xff1a;深度解构与未来展望 在数字化浪潮汹涌的时代&#xff0c;Web前端作为用户与互联网世界的桥梁&#xff0c;其重要性不言而喻。对于前端开发者而言&#xff0c;一份精心规划的Web前端策略&#xff0c;不仅是项目成功的基石&#xff0c;更是技术进步的引…

Foundation Model 通用大模型的评测体系

随着大模型评测需求逐渐增加,相关研究也进一步深入。大模型相比传统模 型&#xff0c;泛化能力更强、灵活性更高、适应性更广&#xff0c;多任务、多场景&#xff0c;评测维度、评测指标和数 据集更复杂&#xff0c;面向大模型的评估方法、评测基准、测试集成为新的研究课题。 …

Qt图表类介绍

本文主要介绍QCharts相关的模块及类。 Qt中图表模块有以下几种类型&#xff1a;折线图&#xff0c;样条曲线图&#xff0c;面积图&#xff0c;散点图&#xff0c;条形图&#xff0c;饼图&#xff0c;方块胡须图&#xff0c;蜡烛图&#xff0c;极坐标图。 QCharts的图表框架类似…

数据Ant-Design-Vue动态表头并填充

Ant-Design-Vue是一款基于Vue.js的UI组件库&#xff0c;广泛应用于前端开发中。在Ant-Design-Vue中&#xff0c;提供了许多常用的组件&#xff0c;包括表格组件。表格组件可以方便地展示和处理大量的数据。 在实际的开发中&#xff0c;我们经常会遇到需要根据后台返回的数据动…

【Python】Selenium基础入门

Selenium基础入门 一、Selenium简介二、Selenium的安装三、Selenium的使用1.访问web网站2.元素定位根据标签 id 获取元素根据标签 name 属性的值获取元素根据 Xpath 语句获取元素根据标签名获取元素根据CSS选择器获取元素根据标签的文本获取元素&#xff08;精确定位&#xff0…

“论边缘计算及应用”必过范文,突击2024软考高项论文

论文真题 边缘计算是在靠近物或数据源头的网络边缘侧&#xff0c;融合网络、计算、存储、应用核心能力的分布式开放平台(架构)&#xff0c;就近提供边缘智能服务。边缘计算与云计算各有所长&#xff0c;云计算擅长全局性、非实时、长周期的大数据处理与分析&#xff0c;能够在…

宝塔面板和 LNMP 环境下反代 HFish 蜜罐平台的正确方法

最近明月在热心站长好友的支持下搭建了安全、简单、有效并永久免费的蜜罐平台 HFish,因为 HFish 默认是以 https://IP:端口 的 Web 链接形式提供访问的,这会暴露蜜罐平台的真实服务器 IP 不说,还非常不便于快速的访问(反正明月是记不住 IP 的),所以就需要给部署好的 HFis…

OS复习笔记ch8-3

驻留集 驻留集&#xff1a;指请求分页存储管理中给进程分配的内存块的集合。 在采用了虚拟存储技术的系统中&#xff0c;驻留集大小一般小于进程的总大小。 驻留集&#xff0c;从某种角度可以看成是进程可以常驻内存的内存块的集合。 若驻留集太小&#xff0c;会导致缺页频繁…

excel vlookup首行值不对

因为数据表查找区间不够大。行数要足够大。 好像和精确匹配有关

Windows 10 找不到Microsoft Edge 浏览器

下载链接 了解 Microsoft Edge 手动下载浏览器 问题说明 一般来说&#xff0c;windows10系统应该是自带浏览器edge的&#xff0c;但有的电脑就是没有找到edge浏览器&#xff0c;可能系统是精简过的&#xff0c;可能是被卸载了。如下&#xff0c;控制面板确实没找到程序。 ​ …

大模型相关:ChatGPT的原理与架构

一、大模型面临的挑战 1.1 Transformer模型的缺陷&#xff1a; 与RNN相比Transformer面临以下挑战&#xff1a; 并行计算能力不足。RNN需要按序处理序列数据中的每个时间步&#xff0c;这限制了它在训练过程中充分利用现代GPU的并行计算能力&#xff0c;从而影响训练效率。长…

【Vue3】shallowReactive() and shallowReadonly()

历史小剧场 所谓历史&#xff0c;就是过去的事&#xff0c;它的残酷之处在于&#xff1a;无论你哀嚎&#xff0c;悲伤&#xff0c;痛苦&#xff0c;落寞&#xff0c;追悔&#xff0c;它都无法改变。 一具有名的尸体躺在无数无名的尸体上&#xff0c;这就是所谓的霸业。---- 《明…

C#操作MySQL从入门到精通(18)——使用组合查询

前言: 我们有时候需要使用多条select语句来获取查询结果,这时候就可以使用union这个关键字来实现组合查询,详细介绍如下: 1、union union这个组合查询,会自动将重复的行去掉 使用union来组合两条select语句 string sql = string.Empty;if (radioButton_UNION.Checked){…

SQL主键回显

目录 一 业务场景 二 如何使用 一 业务场景 当我们在一个业务功能下操作多张表时&#xff0c;当另一个表数据需要上一个表刚插入的数据的ID时&#xff0c;就需要使用到主键回显。 比如我现在有两张表&#xff0c;一张是菜品表&#xff0c;一张是口味表。而我一个菜品应该会有多…

关于Input【type=number】可以输入e问题及解决方案

一、为什么 因为在数学里e 代表无理数&#xff0c;e是自然对数的底数&#xff0c;同时它又是一个无限不循环小数&#xff0c;所以我们在输入 e 时&#xff0c;输入框会默认 e 是数字&#xff0c;从而没有对它进行限制。 二、解决方案 小提示&#xff1a;vue下监听事件需要加n…

Llama模型家族之Stanford NLP ReFT源代码探索 (二)Intervention Layers层

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

simulink中显示模块中的名字

simulink/matlab version: R2022a 改动前&#xff1a;X那里没有显示名字&#xff1b; 改动方法&#xff1a; 1&#xff09;鼠标左键点击待显示模块&#xff1b; 2&#xff09;菜单栏新增 模块这个选项&#xff1b; 3&#xff09;点击自动名称&#xff1b; 4) 点击名称打开…