项目实战典型案例1——redis只管存不管删除 让失效时间删除的问题
redis只管存不管删除 让失效时间删除的问题
- 一:背景介绍
- 二:思路&方案
- 三:代码模拟
- 1.错误示范
- 通过班级id查询课程名称
- 执行结果
- 通过班级id修改课程名称(并没有删除对应缓存)
- 执行结果
- 2.正确示范
- 在错误示范的更新接口上添加删除缓存的代码
- 四:总结
- 五:升华
一:背景介绍
本篇博客是对项目开发中出现的redis只管存不管删除 让失效时间删除的问题进行的总结和改进。目的是将经历转变为自己的经验。通过博客的方式分享给大家,大家一起共同进步和提高。
代码逻辑
- 通过redis查询该课程下所有班级的信息
- 如果没有从redis中查询到数据就从数据库中查询并存入到redis中一份
存在的问题
3. 并没有在更新课程下班级数据的时候删除缓存,会导致如果我更新了该课程下的班级数据,会导致缓存中的数据与数据中的数据不一致,当我再次查询数据的时候,如果我的key键没有过期会直接从redis中查询数据,但是查询的数据是没有更新之前的数据。如果我key键正好过期了才会从数据库中查询最新的数据,并更新到缓存中。
二:思路&方案
保证缓存数据与数据库中数据同步的方案。
- 查询的时候如果缓存存在则从缓存中获取,如果缓存不存在则从数据库中获取数据,并将获取到的数据存储在缓存中。
- 更新数据的时候删除缓存。
三:代码模拟
通过java maven项目模拟redis只管存不管删除 让失效时间删除的问题 进行错误示范和正确示范
代码环境:java maven项目、mysql,redis
pom.xml文件
<dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.3.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version><scope>compile</scope></dependency></dependencies>
1.错误示范
通过班级id查询课程名称
package org.example.controller;import org.example.dao.UserInfoDao;
import org.example.entity.CourseConfiguration;
import redis.clients.jedis.Jedis;/*** @author : [WangWei]* @version : [v1.0]* @className : UserInfoController* @description : [描述说明该类的功能]* @createTime : [2022/11/30 11:43]* @updateUser : [WangWei]* @updateTime : [2022/11/30 11:43]* @updateRemark : [描述说明本次修改内容]*/
public class SelectCourseNameByClassId {/** @description:通过班级id查询课程名称* @author: wangwei* @date: 2023/3/4 14:24* @param: [args]* @return: void**/public static void main(String[] args) {//构造jedis,连接redis 并设置超时时间为100秒,在jedis的默认构造方法中,超时的时间一般被默认设置为2000毫秒,也就是2秒。Jedis jedis=new Jedis("ip",端口号,100000);jedis.auth("密码");CourseConfiguration courseConfiguration=null;//查询redisString courseName = jedis.get("WangWei:ClassId");if(courseName==""||courseName==null){//从数据库中查询UserInfoDao userInfoDao=new UserInfoDao();courseConfiguration = userInfoDao.selectCourseNameByClassId(55801751);//存入redis 并设置过期时间60秒jedis.set("WangWei:ClassId",courseConfiguration.getCourse_name());jedis.expire("WangWei:ClassId",60);System.out.println(courseConfiguration.getCourse_name());}else {System.out.println(courseName);}}}
执行结果
通过班级id修改课程名称(并没有删除对应缓存)
package org.example.controller;import org.example.dao.UserInfoDao;
import org.example.entity.CourseConfiguration;
import org.example.utils.RedisConfig;
import redis.clients.jedis.Jedis;/*** @author : [WangWei]* @version : [v1.0]* @className : UpdateCourseNameByClassId* @description : [描述说明该类的功能]* @createTime : [2023/3/4 14:26]* @updateUser : [WangWei]* @updateTime : [2023/3/4 14:26]* @updateRemark : [描述说明本次修改内容]*/
public class UpdateCourseNameByClassId {/** @description:通过通过班级id修改班级名称* @author: wangwei* @date: 2023/3/4 14:27* @param: [args]* @return: void**/public static void main(String[] args) {//修改班级名称UserInfoDao userInfoDao=new UserInfoDao();userInfoDao.updateCourseNameByClassId(55801751,"ARPro计算机思维课程-开发班课");// //连接redis
// Jedis jedis=new Jedis("82.157.199.3",6379,100000);
// jedis.auth("000415");
// //删除key键
// jedis.del("WangWei:ClassId");System.out.println("修改成功!");}
}
执行结果
这个时候我们再执行 通过班级id查询课程名称的接口由于WangWei:ClassId这个key键还没有过期,会发现查询的还是之前没有修改的课程名称。数据出现不一致。
当key键WangWei:ClassId过期时由于查询的是数据库中的数据,所以数据是一致的。
2.正确示范
- 查询的时候如果缓存存在则从缓存中获取,如果缓存不存在则从数据库中获取数据,并将获取到的数据存储在缓存中。
- 更新数据的时候删除缓存。
在错误示范的更新接口上添加删除缓存的代码
package org.example.controller;import org.example.dao.UserInfoDao;
import redis.clients.jedis.Jedis;/*** @author : [WangWei]* @version : [v1.0]* @className : UpdateCourseNameByClassId* @description : [描述说明该类的功能]* @createTime : [2023/3/4 14:26]* @updateUser : [WangWei]* @updateTime : [2023/3/4 14:26]* @updateRemark : [描述说明本次修改内容]*/
public class UpdateCourseNameByClassId {/** @description:通过通过班级id修改班级名称* @author: wangwei* @date: 2023/3/4 14:27* @param: [args]* @return: void**/public static void main(String[] args) {//修改班级名称UserInfoDao userInfoDao=new UserInfoDao();userInfoDao.updateCourseNameByClassId(55801751,"ARPro计算机思维课程-开发班课");//连接redisJedis jedis=new Jedis("82.157.199.3",6379,100000);jedis.auth("000415");//删除key键jedis.del("WangWei:ClassId");System.out.println("修改成功!");}
}
通过以上的缓存同步测试,就可以保证缓存中的数据与实际数据库中的数据保持一致。
四:总结
1.出现这次redis只管存不管删除的问题,在于对于redis在实际项目中的使用不够熟悉了解,不清楚缓存同步的策略。推荐需要对redis参照官网进行系统性的学习,以及与其他高人进行讨论交流。
2.其实对于此次问题,如果没有遇到这个案例,自己也很有可能会同样的获取,由于自己本身对于redis的使用没有涉及到,以及考虑到redis缓存同步。
五:升华
通过这次的案例分析,对于认知上需要提升的点,自己也有了针对性提升对于知识认知上的方式方法。如思维导图,三篇读数法,参照官网对例如redis进行快速浏览,通过思维导图宏观了解,提升认知,不怕不知道就怕不知道。
相关文章:

项目实战典型案例1——redis只管存不管删除 让失效时间删除的问题
redis只管存不管删除 让失效时间删除的问题一:背景介绍二:思路&方案三:代码模拟1.错误示范通过班级id查询课程名称执行结果通过班级id修改课程名称(并没有删除对应缓存)执行结果2.正确示范在错误示范的更新接口上添…...

@RequestParam和@PathVariable的用法与区别
PathVariable PathVariable 映射 URL 绑定的占位符带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义通过 PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占…...

【大数据 AI 人工智能】数据科学家必学的 9 个核心机器学习算法
如今,机器学习正改变着我们的世界。借助机器学习(ML),谷歌在为我们推荐搜索结果,奈飞在为我们推荐观看影片,脸书在为我们推荐可能认识的朋友。 机器学习从未像在今天这样重要。但与此同时,机器学习这一领域也充斥着各种术语,晦涩难懂,各种机器学习的算法每年层出不穷…...

IronPDF for .NET 2023.2.4 Crack
适用于 .NET 2023.2.4 的 IronPDF 添加对增量 PDF 保存的支持。 2023 年 3 月 2 日 - 10:23新版本 特征 添加了对 IronPdfEngine Docker 的支持。 添加了对增量 PDF 保存的支持。 重新设计了 PDF 签名和签名。 删除了 iTextSharp 依赖项。 在文本页眉/页脚中添加了 DrawDivider…...

3.4-前端的10个问题
01、null和undefined undefined是全局对象的一个属性,当一个变量没有赋值或者访问一个对象不存在的属性,这时候都是undefined。 null:表示是一个空对象。在需要释放一个对象的时候,直接赋值为null即可。 02、箭头函数 箭头函数…...

开发手册——一、编程规约_9.其他
这篇文章主要梳理了在java的实际开发过程中的编程规范问题。本篇文章主要借鉴于《阿里巴巴java开发手册终极版》 下面我们一起来看一下吧。 1. 【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。 说明:不要在方法…...

23.3.4打卡 AtCoder Beginner Contest 291(Sponsored by TOYOTA SYSTEMS)A~E
F题题面都看不懂嘞!开摆! 没找到合适的markdown, 截图网页翻译了我真是天才 比赛链接: https://atcoder.jp/contests/abc291 A题 题意 给出一个字符串, 找到第一个大写字母的下标 简单题就不多说了, 直接放代码 代码 void solve() {cin>>str;nstr.size();str"…...

Gem5模拟器,一些运行的小tips(十一)
一些基础知识,下面提到的东西与前面的文章有一定的关系,感兴趣的小伙伴可以看一下: (21条消息) Gem5模拟器,全流程运行Chiplet-Gem5-SharedMemory-main(十)_好啊啊啊啊的博客-CSDN博客 Gem5模拟器…...

【JAVA】List接口
🏆今日学习目标:List接口 😃创作者:颜颜yan_ ✨个人主页:颜颜yan_的个人主页 ⏰本期期数:第四期 🎉专栏系列:JAVA List接口一、ArrayList二、LinkedList总结一、ArrayList ArrayLis…...

Hbase RegionServer的核心模块
RegionServer是HBase系统中最核心的组件,主要负责用户数据写入、读取等基础操作。RegionServer组件实际上是一个综合体系,包含多个各司其职的核心模块:HLog、MemStore、HFile以及BlockCache。 一、RegionServer内部结构 RegionServer是HBas…...

【Java开发】JUC进阶 01:Lock锁详解
1 Lock锁介绍已经在【JUC基础】04简单介绍过了,本文做进一步的拓展,比如公平锁和非公平锁、📌 明白锁的核心四个对象:线程,共享资源,锁,锁操作包括线程如何操作资源,使用锁锁哪个资源…...

关于登录校验的解决方案以及原理(回顾知识点)--项目开发那点事(自问自答版本)
开始前奏: 嘻嘻😄 通常一个完整的系统,需要安全性的保证。如登录校验,登录成功后,才可以访问服务资源。在服务端渲染项目中,我们通常使用 session来进行登录校验。在前后端分离的场景中,很多时…...

【数据结构】邻接矩阵和邻接图的遍历
写在前面 本篇文章开始学习数据结构的图的相关知识,涉及的基本概念还是很多的。本文的行文思路:学习图的基本概念学习图的存储结构——本文主要介绍邻接矩阵和邻接表对每种结构进行深度优先遍历和广度优先遍历先识概念话不多说,狠活献上学习思想等等&…...

设计跳表(动态设置节点高度)
最近学习redis的zset时候,又看到跳表的思想,突然对跳表的设置有了新的思考 这是19年设计的跳表,在leetcode的执行时间是200ms 现在我对跳表有了新的想法 1、跳表的设计,类似二分查找,但是不是二分查找,比较…...

基于神经辐射场(Neural Radiance Fileds, NeRF)的三维重建- 简介(1)
Nerf简介 Nerf(neural Radiance Fileds) 为2020年ICCV上提出的一个基于隐式表达的三维重建方法,使用2D的 Posed Imageds 来生成(表达)复杂的三维场景。现在越来越多的研究人员开始关注这个潜力巨大的领域,也…...

【AI面试】NMS 与 Soft NMS 的辨析
往期文章: AI/CV面试,直达目录汇总【AI面试】L1 loss、L2 loss和Smooth L1 Loss,L1正则化和L2正则化 一、NMS 非极大值抑制(Non-Maximum Suppression,NMS),并不是深度学习时期,目标…...

一文让你彻底理解Linux内核多线程(互斥锁、条件变量、读写锁、自旋锁、信号量)
一、互斥锁(同步) 在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在…...

利用python写一个gui小公举--环境搭建
文章目录背景搭建环境安装必要库添加工具快捷方式检验背景 在实习过程中遇到一个问题,某项目是通过python代码实现的,而且需要一直修改参数实现功能,过程有些繁琐。虽然师兄用PHP study搭了一个网站用于查看结果,但是还是过于繁琐…...

英飞凌Tricore实战系列02_ENDINIT属性看门狗原理及应用
目录 1.概述2.ENDINIT功能及使用2.1 ENDINIT属性2.2 改写受ENDINIT保护寄存器的步骤3. Tricore 看门狗介绍及使用3.1 看门狗系统介绍3.1.1 安全看门狗介绍3.1.2 CPU看门狗介绍3.2 看门狗模式介绍3.2.1 Time-out模式3.2.2 正常模式(Normal Mode)3.2.3 禁用模式(Disabled Mode…...

Java Number类
Java Number 类是一个抽象类,它是所有数字类的基类。Java 中的数字类包括 Byte、Short、Integer、Long、Float 和 Double,它们都继承自 Number 类。Java Number 类提供了一些常用的方法,可以用于将数字类型转换为不同的格式,以及进…...

C++构造和析构
欢迎来观看温柔了岁月.c的博客 目前 设有C学习专栏 C语言项目专栏 数据结构与算法专栏 目前主要更新C学习专栏,C语言项目专栏不定时更新 待C专栏完毕,会陆续更新C项目专栏和数据结构与算法专栏 一周主要三更,星期三,星期五&#x…...

docker安装即docker连接mysql(window)
一 安装docker 1.什么是docker Docker容器与虚拟机类似,但二者在原理上不同。容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。 2.WSL2 WSL,即Windows Subsystem on Linux,中…...

HMM-维特比算法
HMM-维特比算法(viterbi)HMM回顾隐马科夫链解法:维特比算法(Viterbi)HMM回顾 最终的公式可以解释主要分为两个部分: P(xi|yi),发射概率,字面意思是从一个词性中发射/生成出某一个单…...

【C++初阶】2. 类和对象_1
1. 面向过程和面向对象的初步认识 2. 类的引入 C语言结构体中只能定义变量,在C中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量&#…...

kotlin把函数作为参数转递给另一个函数
kotlin把函数作为参数转递给另一个函数 fun say(s: String, foo: (String) -> Unit) {print("hello")foo(s) }fun hi(str: String) {println(str) }fun main(args: Array<String>) {say("hello", ::hi) } 输出: hellohello...

海思嵌入式开发-005-OpenHarmony源码编译问题
海思嵌入式开发-005-OpenHarmony源码编译问题一、问题描述二、解决方案2.1解决原理2.2获取OpenHarmony 3.1.1 Release源码2.3最后解决问题,编译成功。一、问题描述 按照链接拉取master源码,出现如下问题,打开build.log文件 提示相应位置的文…...

指针的进阶续(笔试题强化练习)
写在前面:在上次我们学习了指针的相关类型的知识,对指针家族的成员基本有了了解,这次让我们跟着一些题目来练习和补充一些知识,这有助于我们强化理解这些知识。 话不多说,我们马上开始: 1.指针和数组的笔…...

一个供参考的计算机的学习路线
本文是介绍如何成为一个Geek,一个真正的计算机高手。 适合有成为IT领域技术大牛的人参考。 写给大一新生和所有向深耕IT领域的人,避免走一些弯路。 仅代表个人想法,供批判性参考。 第一门入门的必备功课-语法与算法 什么是计算机?…...

React(五):受控组件、高阶组件、Portals、Fragment、CSS的编写方式
React(五)一、受控组件1.什么是受控组件(v-model)2.收集表单数据:input和单选框3.收集表单数据:下拉框二、非受控组件三、高阶组件1.什么是高阶组件2.高阶组件的应用13.高阶组件的应用2-注入Context4.高阶组件的应用3-登录鉴权5.高…...

MATLAB——系统环境
MATLAB概述MATLAB的发展MATLAB:MATrix LABoratory1980年前后,Cleve Moler教授编写的Linpack 和Eispack的接口程序。1984年,MATLAB第1版(DOS版)1992年,MATLAB4.0版1994年,MATLAB 4.2版1997年,MATLAB 5.0版1999年&#x…...