使用Spring Boot实现Redis多数据库缓存
Redis多数据库存储实现用户行为缓存
在我的系统中,为了优化用户行为数据的存储与访问效率,我引入了Redis缓存,并将数据分布在不同的Redis数据库中。通过这种方式,可以减少单一数据库的负载,提高系统的整体性能。
主要实现步骤
-
Redis配置
- 配置两个Redis连接工厂,分别用于存储Token和用户行为数据。
- 创建对应的RedisTemplate实例,指定不同的连接工厂及序列化方式。
-
用户行为服务
- 通过
UserBehaviorService
接口及其实现类UserBehaviorServiceImpl
,实现对用户点赞、收藏、评论、浏览行为的记录。 - 在操作数据库的同时,将用户行为数据存储到Redis中以提高读取效率。
- 通过
-
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();}
}
相关文章:
使用Spring Boot实现Redis多数据库缓存
Redis多数据库存储实现用户行为缓存 在我的系统中,为了优化用户行为数据的存储与访问效率,我引入了Redis缓存,并将数据分布在不同的Redis数据库中。通过这种方式,可以减少单一数据库的负载,提高系统的整体性能。 主要…...
揭秘newSingleThreadExecutor:深度解析与源码探秘
1. 概述 newSingleThreadExecutor是Java线程池框架中Executors类的一个静态方法,它返回一个线程池实例,该线程池维护一个单一的工作线程来执行任务。这个线程池的特性在于它保证了所有提交的任务会按照它们在队列中的顺序依次执行,而不会并发执行。它适用于需要保证任务顺序…...

使用python绘制三维散点图
使用python绘制三维散点图 三维散点图三维散点图的用途效果代码 三维散点图 三维散点图(3D Scatter Plot)是一种用于展示三维数据的图表。与二维散点图类似,三维散点图通过点在三维空间中的位置来表示数据点的三个特征。每个点在 x、y 和 z …...

Vue51-插件
一、插件的定义 vue里面的插件,类似于游戏的外挂。 vue中插件的本质:一个对象,里面必须包含install方法。 二、插件的使用 2-1、创建一个插件js文件(写在src中plugins.js) 2-2、应用插件:Vue.use(插件) …...
python将一个整数转为字符串列表
如果你想要将一个整数转换为字符串列表,其中每个数字(0-9)都是列表中的一个元素,你可以先将整数转换为字符串,然后遍历这个字符串,将每个字符添加到列表中。这里是一个简单的示例: # 假设你有一…...

PTA 6 - 20 汉诺塔问题(py 递归)
这道题是一道比较典型的递归问题,他跟斐波那契数列的本质是一样的,大家自己动手推理一下,非常好推 参考代码: def hanoi(n,a,b,c):global stepif n 1:print(a,"->",c)step 1else:hanoi(n-1,a,c,b)print(a,"…...

深度学习Day-20:DenseNet算法实战 乳腺癌识别
🍨 本文为:[🔗365天深度学习训练营] 中的学习记录博客 🍖 原作者:[K同学啊 | 接辅导、项目定制] 一、 基础配置 语言环境:Python3.8编译器选择:Pycharm深度学习环境: torch1.12.1c…...

给类设置serialVersionUID
第一步打开idea设置窗口(setting窗口默认快捷键CtrlAltS) 第二步搜索找到Inspections 第三步勾选主窗口中Java->Serializations issues->下的Serializable class without serialVersionUID’项 ,并点击“OK”确认 第四步鼠标选中要加…...
Android之实现两段颜色样式不同的文字拼接进行富文本方式的显示
一、使用SpannableString进行拼接 1、显示例子 前面文字显示红色,后面显示白色,显示在一个TextView中,可以自动换行 发送人姓名: 发送信息内容2、TextView <TextViewandroid:id"id/tv_msg"android:layout_width"wrap_c…...

GenICam标准(五)
系列文章目录 GenICam标准(一) GenICam标准(二) GenICam标准(三) GenICam标准(四) GenICam标准(五) GenICam标准(六) 文章目录 系列文…...

《人生海海》读后感
麦家是写谍战的高手,《暗算》《风声》等等作品被搬上荧屏后,掀起了一阵一阵的收视狂潮。麦家声名远扬我自然是知道的,然而我对谍战似乎总是提不起兴趣,因此从来没有拜读过他的作品。这几天无聊时在网上找找看看,发现了…...

SpringBoot自定义Starter及原理分析
目录 1.前言2.环境3.准备Starter项目4.准备AutoConfigure项目4.1 准备类HelloProperties4.2 准备类HelloService4.3 准备类HelloServiceAutoConfiguration4.4 创建spring.factories文件并引用配置类HelloServiceAutoConfiguration4.5 安装到maven仓库 5.在其他项目中引入自定义…...

YOLOv10网络架构及特点
YOLOv10简介 YOLOv10是清华大学的研究人员在Ultralytics Python包的基础上,引入了一种新的实时目标检测方法,解决了YOLO 以前版本在后处理和模型架构方面的不足。通过消除非最大抑制(NMS)和优化各种模型组件,YOLOv…...

基于单片机的多功能智能小车设计
第一章 绪论 1.1 课题背景和意义 随着计算机、微电子、信息技术的快速发展,智能化技术的发展速度越来越快,智能化与人们生活的联系也越来越紧密,智能化是未来社会发展的必然趋势。智能小车实际上就是一个可以自由移动的智能机器人,比较适合在人们无法工作的地方工作,也可…...

Python时间序列分析库
Sktime Welcome to sktime — sktime documentation 用于ML/AI和时间序列的统一API,用于模型构建、拟合、应用和验证支持各种学习任务,包括预测、时间序列分类、回归、聚类。复合模型构建,包括具有转换、集成、调整和精简功能的管道scikit学习式界面约定的交互式用户体验Pro…...

算法设计与分析 实验1 算法性能分析
目录 一、实验目的 二、实验概述 三、实验内容 四、问题描述 1.实验基本要求 2.实验亮点 3.实验说明 五、算法原理和实现 问题1-4算法 1. 选择排序 算法实验原理 核心伪代码 算法性能分析 数据测试 选择排序算法优化 2. 冒泡排序 算法实验原理 核心伪代码 算…...

FPGA NET
描述 网络是一组相互连接的引脚、端口和导线。每条电线都有一个网名 识别它。两条或多条导线可以具有相同的网络名称。所有电线共享一个公用网络 名称是单个NET的一部分,并且连接到这些导线的所有引脚或端口都是电气的 有联系的。 当net对象在 将RTL源文件细化或编译…...
把服务器上的镜像传到到公司内部私有harbor上,提高下载速度
一、登录 docker login https://harbor.cqxyy.net/ -u 账号 -p 密码 二、转移镜像 minio 2024.05版 # 指定tag docker tag minio/minio:RELEASE.2024-05-10T01-41-38Z harbor.cqxyy.net/customer-software/minio:RELEASE.2024-05-10T01-41-38Z# 推送镜像 docker push harbo…...

1055 集体照(测试点3, 4, 5)
solution 从后排开始输出,可以先把所有的学生进行排序(身高降序,名字升序),再按照每排的人数找到中间位置依次左右各一个进行排列测试点3, 4, 5:k是小于10的正整数,则每…...

AI 定位!GeoSpyAI上传一张图片分析具体位置 不可思议! ! !
🏡作者主页:点击! 🤖常见AI大模型部署:点击! 🤖Ollama部署LLM专栏:点击! ⏰️创作时间:2024年6月16日12点23分 🀄️文章质量:94分…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...