使用Redis做缓存的小案例
如果不了解Redis,可以查看本人博客:Redis入门
Redis基于内存,因此查询速度快,常常可以用来作为缓存使用,缓存就是我们在内存中开辟一段区域来存储我们查询比较频繁的数据,这样,我们在下一次查询的时候,会直接去内存中查询,如果命中(查询到),就直接返回,否则就去数据库等在磁盘位置存储的数据进行查询,去磁盘硬盘等位置查询数据就比较慢了。因此,用好缓存对于我们的用户体验也是很重要的。
本文基于springboot+mybatisplus+Redis进行实现。
首先创建一个springboot项目:

不勾选依赖:

导入依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
配置application.yaml
spring:redis:host: localhostport: 6379password: 123456datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rooturl: jdbc:mysql://localhost:3306/hongyan_sso?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true
编写实体类:
package com.qcby.springbootdata.pojo;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@TableName("t_user")
@Data
public class User {private Long id;private String userName;private String password;private String nickName;
}
编写mapper:
package com.qcby.springbootdata.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.springbootdata.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.tomcat.websocket.BackgroundProcess;@Mapper
public interface UserMapper extends BaseMapper<User> {
}
编写controller:
package com.qcby.springbootdata.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qcby.springbootdata.mapper.UserMapper;
import com.qcby.springbootdata.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;@RestController
@Slf4j
public class UserController {@Resourceprivate UserMapper userMapper;@Resourceprivate RedisTemplate<String,String> redisTemplate;@GetMapping("/get-user-by-nick")public String getUserByNick(Long id){String key = buildKey(String.valueOf(id));if(Boolean.TRUE.equals(redisTemplate.hasKey(key))){log.info("命中缓存,id:{}",id);return redisTemplate.boundValueOps(key).get();}User userPO = userMapper.selectById(id);if(userPO == null){redisTemplate.boundValueOps(key).set("暂无此人");return "暂无此人";}redisTemplate.boundValueOps(key).set(userPO.toString());return userPO.toString();}/*** 更新用户* 一般情况下,修改后删除就行了* 但是并发比较高,而且对数据比较敏感,比如说金钱,需要双删** @param userId 用户id* @param nickName 尼克名字* @return {@link String}* @throws InterruptedException 中断异常*/@GetMapping("/update-user-by-nick")public String updateUser(Long userId,String nickName) throws InterruptedException {User userPO = new User();userPO.setId(userId);userPO.setNickName(nickName);//这一步删除是为了保证,当sql指令发送给mysql以后,查询出来的值还是旧的redisTemplate.delete(buildKey(userId.toString()));userMapper.updateById(userPO);//这一步是为保证在sql指定发送给mysql的时候,来了查询,如果说这个时候的查寻还是修改之前的,导致缓存不更新redisTemplate.delete(buildKey(userId.toString()));return "22";}/*** 缓存预热*/@PostConstructpublic void initCache(){log.info("=========进行缓存预热=======================");List<Long> id = Arrays.asList(101110L,101112L,101116L,101118L);List<User> userPOS = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getId, id));userPOS.stream().forEach(item->{redisTemplate.boundValueOps(buildKey(item.getId().toString())).set(item.toString());});}private String buildKey(String Id){return "user:Id_"+Id;}
}
我们看一下controller中的思路:
①.@GetMapping("/get-user-by-nick")
public String getUserByNick(Long id)
这个方法首先根据给出的查询参数构造Redis的key,我们查询Redis或者存Redis数据通常会构造一个key,按照这个key来存储值。
首先从Redis数据库中查询,是否存在该查询结果的数据,如果存有,就直接拿取返回即可,否则走下一步。
然后从数据库中查询需要的数据,首先判断这个数据是否存在,如果存在就存入Redis该数据值,否则说明不存在,直接存储“无此数据”即可。
这个函数的大体思路就是,有数据就拿,没数据就存一个下次方便拿。
②.@GetMapping("/update-user-by-nick")
public String updateUser(Long userId,String nickName)
这个函数就是用来更新数据库数据,并且做到数据库与缓存之间保持同步。主要是考虑并发情况下,保证缓存数据和数据库数据的最终一致性。更新前删除缓存中的数据,保证尽可能的让其他进程或线程感知到数据库变化,进而在缓存中没有命中,进数据库中查询数据,此时,数据可能已经被更新了,或者还没有更新。
第二次删除就是为了保证数据更新以后,删除缓存中数据,让其他进程或线程在缓存中无命中,进而进入数据库读取最新的数据,保证了最终一致性。
③.@PostConstruct
public void initCache()
这个方法主要是做缓存预热,在查询数据之前,预先将访问频繁的数据存入缓存,进而提高缓存命中,提高查询效率。
相关文章:
使用Redis做缓存的小案例
如果不了解Redis,可以查看本人博客:Redis入门 Redis基于内存,因此查询速度快,常常可以用来作为缓存使用,缓存就是我们在内存中开辟一段区域来存储我们查询比较频繁的数据,这样,我们在下一次查询…...
剧本杀小程序功能介绍
剧本杀功能介绍 剧本杀,一种融合了角色扮演与推理解谜的社交游戏,近年来在年轻人中越来越受欢迎。它不仅可以锻炼参与者的逻辑推理能力,还能增进朋友间的感情,提升团队协作能力。下面,我们将详细介绍剧本杀的核心功能…...
C#基础语法学习笔记(传智播客学习)
最近在学习C#开发知识,跟着传智播客的视频学习了一下,感觉还不错,整理一下学习笔记。 C#基础语法学习笔记 1.背景知识2.Visual Studio使用3.基础知识4.变量5.运算符与表达式6.程序调试7.判断结构8.循环结构9.常量、枚举类型10.结构体类型11.数…...
图论01-DFS和BFS(深搜和广搜邻接矩阵和邻接表/Java)
1.深度优先理论基础(dfs) dfs的两个关键操作 搜索方向,是认准一个方向搜,直到碰壁之后再换方向 换方向是撤销原路径,改为节点链接的下一个路径,回溯的过程。dfs解题模板 void dfs(参数) {if (终止条件) {存放结果;return;}for …...
【Python】Miniconda+Vscode+Jupyter 环境搭建
1.安装 Miniconda Conda 是一个开源的包管理和环境管理系统,可在 Windows、macOS 和 Linux 上运行,它可以快速安装、运行和更新软件包及其依赖项。使用 Conda,我们可以轻松在本地计算机上创建、保存、加载和切换不同的环境 Conda 分为 Anaco…...
Redis消息队列与thinkphp/queue操作
业务场景 场景一 用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。 遇到两个问题: 由于代码是串行方式,流程大致为:开…...
【Ubuntu】常用命令
一般操作 pwd(present working directory) 显示当前的工作目录/路径。 cd (change directory) 改变目录,用于输入需要前往的路径/目录。 有一些特殊命令也很常用 : 解释 前往同一级的另一个目录 cd ../directory name cd .. 表示进入上…...
稀碎从零算法笔记Day22-LeetCode:
题型:链表 链接:2. 两数相加 - 力扣(LeetCode) 来源:Leet 题目描述 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 …...
Nacos下载和安装
(1)下载地址和版本 下载地址:Releases alibaba/nacos GitHub 解压在没有中文及空格的文件夹 (2)启动nacos服务 在bin目录下,打开命令行,输入 启动命令:sh startup.sh -m standalone - Linux/Unix/Mac …...
pandas简介(python)
pandas是什么 Pandas 是一个开源的第三方 Python 库,从 Numpy 和 Matplotlib 的基础上构建而来,享有数据分析“三剑客之一”的盛名(NumPy、Matplotlib、Pandas)。Pandas 已经成为 Python 数据分析的必备高级工具,它的…...
个人网站制作 Part 13 添加搜索功能[Elasticsearch] | Web开发项目
文章目录 👩💻 基础Web开发练手项目系列:个人网站制作🚀 添加搜索功能🔨使用Elasticsearch🔧步骤 1: 安装Elasticsearch🔧步骤 2: 配置Elasticsearch🔧步骤 3: 创建索引 …...
Springboot+vue的仓库管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue的仓库管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层…...
vue3 + vite 实现一个动态路由加载功能
假设后端返回的格式是这样子 {"menu": [{"path": "/admin","name": "adminLayout","redirect": "/admin/index","componentPath": "/layout/admin/index.vue","children&quo…...
【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024)
【征稿进行时|见刊、检索快速稳定】2024年区块链、物联网与复合材料与国际学术会议 (ICBITC 2024) 大会主题: (主题包括但不限于, 更多主题请咨询会务组苏老师) 区块链: 区块链技术和系统 分布式一致性算法和协议 块链性能 信息储存系统 区块链可扩展性 区块…...
若依jar包运行脚本,从零到一:用Bash脚本实现JAR应用的启动、停止与监控
脚本使用说明: 启动应用:sh app.sh start停止应用:sh app.sh stop检查应用状态:sh app.sh status重启应用:sh app.sh restart 注意事项: 请确保你的系统上安装了 Java 环境,并且 ruoyi-admin…...
Unix运维_FreeBSD-13.1临时环境变量设置(bin和include以及lib)
Unix运维_FreeBSD-13.1临时环境变量设置(bin和include以及lib) 在 FreeBSD 系统上设置用户环境变量可以通过编辑用户的 Shell配置文件 来实现。 cshrc 与 csh_profile 的区别: cshrc: 每个脚本执行前都执行一遍这个脚本。 csh_profile: 根据不同使用者用户名, 会先去其 home…...
Apache Dolphinscheduler - 无需重启 Master-Server 停止疯狂刷日志解决方案
记录的是一个 3.0 比较难搞的问题,相信不少使用过 3.0 的用户都遇到过 Master 服务中存在一些工作流或者任务流一直不停的死循环的问题,导致疯狂刷日志。不过本人到现在也没找到最关键的触发原因,只是看到一些连锁反应带来的结果…… 影响因素…...
竞争优势:大型语言模型 (LLM) 如何重新定义业务策略
人工智能在内容创作中的突破 在当今快节奏的商业环境中,像 GPT-4 这样的大型语言模型 (LLM) 不再只是一种技术新颖性; 它们已成为重新定义跨行业业务战略的基石。 从增强客户服务到推动创新,法学硕士提供了企业不容忽视的竞争优势。 1. 加强…...
Spring AOP和AspectJ AOP区别
Spring AOP(Aspect-Oriented Programming)和 AspectJ AOP 是两种不同的 AOP 实现方式,它们在实现上有一些区别。下面是它们之间的主要区别: 基于代理 vs 字节码增强: Spring AOP: Spring AOP 是基于代理的…...
FREERTOS信号量详解
信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步,资源管理其实就是用变量来标记现有资源的数量,任务同步其实就是用标志位来控制任务的先后执行顺序,这些概念在操作系统中以及裸机开发中都有所涉及。 FreeR…...
AI编程革命:Codex自动写脚本实战指南
告别重复造轮子:Codex写脚本的技术文章大纲理解Codex的基本能力Codex是基于GPT-3的AI模型,能够将自然语言转换为代码。 支持多种编程语言,包括Python、JavaScript、Go等。 适用于自动化脚本、数据处理、API调用等场景。识别适合自动化的重复任…...
PYTHON学习笔记12(os模块)
OS文件/目录方法os模块是python标准库中的一个重要模块,提供了与操作系统交互的功能,通过此模块可以执行文件操作、目录操作、环境变量管理、进程管理等任务。os模块是跨平台的,可以在不同的操作系统使用相同的代码。使用os模块之前ÿ…...
2026届毕业生推荐的AI辅助写作工具横评
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 处在当下这个节点,生成式人工智能此项技术已然深度地介入到了学术写作的那个领域…...
思源宋体CN:7种字重免费开源字体如何快速提升你的中文设计效果
思源宋体CN:7种字重免费开源字体如何快速提升你的中文设计效果 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 还在为中文排版设计而烦恼吗?找不到既美观又免费…...
RocketMQ可视化控制台(Console)连接不上?排查Namesrv与Broker配置的3个常见坑
RocketMQ可视化控制台连接故障深度排查指南 当你在深夜部署完RocketMQ集群,满心欢喜地打开浏览器准备测试消息流时,却发现控制台始终显示"连接失败"——这种场景对很多开发者来说都不陌生。本文将带你直击三个最容易被忽视的配置陷阱ÿ…...
三步解锁Beyond Compare 5完整功能:免费密钥生成器终极指南
三步解锁Beyond Compare 5完整功能:免费密钥生成器终极指南 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 还在为Beyond Compare 5的30天评估期到期而烦恼吗?想要免费获…...
nli-MiniLM2-L6-H768企业实操:NLI服务接入内部知识库语义检索链路
nli-MiniLM2-L6-H768企业实操:NLI服务接入内部知识库语义检索链路 1. 模型概述 nli-MiniLM2-L6-H768是一个专为自然语言推理(NLI)与零样本分类设计的轻量级交叉编码器(Cross-Encoder)模型。它在保持接近BERT-base精度的同时,通过6层768维的紧凑结构实现…...
别再傻傻穷举了!用Python的`crc32`库和`itertools`高效爆破短字符串CRC(性能优化指南)
突破性能瓶颈:Python高效CRC32爆破实战指南 当我们需要逆向还原短字符串时,CRC32爆破是个常见但耗时的操作。传统多层嵌套循环在面对4字节以上字符串时性能急剧下降——在我的实际测试中,4字节全字符集爆破耗时超过3分钟,而5字节则…...
别再为显卡发愁了!手把手教你用Google Colab免费跑通第一个PyTorch模型
零硬件门槛入门深度学习:Google ColabPyTorch实战指南 当我在大学第一次接触深度学习时,面对动辄上万的GPU配置要求几乎绝望——直到发现了Google Colab这个神器。它不仅能免费提供Tesla T4甚至A100这样的顶级计算卡,还预装了主流深度学习框…...
哔哩下载姬DownKyi终极指南:如何快速掌握B站视频下载技巧
哔哩下载姬DownKyi终极指南:如何快速掌握B站视频下载技巧 【免费下载链接】downkyi 哔哩下载姬downkyi,哔哩哔哩网站视频下载工具,支持批量下载,支持8K、HDR、杜比视界,提供工具箱(音视频提取、去水印等&am…...
