使用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…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
