【SpringBoot篇】解决缓存击穿问题② — 基于逻辑过期方式

🎊专栏【SpringBoot】
🍔喜欢的诗句:天行健,君子以自强不息。
🎆音乐分享【如愿】
🎄欢迎并且感谢大家指出小吉的问题🥰

文章目录

  • 🎍什么是逻辑过期方式
  • ⭐思路
  • 🌹代码

在这里插入图片描述

🎍什么是逻辑过期方式

逻辑过期是一种指定缓存数据失效时间的方式,与物理过期不同。逻辑过期并不直接将缓存中的数据删除,而是在缓存中保留该数据,但标记其为过期,表示该数据已经不再可用。

在逻辑过期的情况下,当有请求查询该数据时,缓存会先检查该数据是否过期,如果过期,则缓存会认为该数据不存在,并重新从数据源获取最新的数据。如果数据没有过期,则直接返回缓存中的数据。需要注意的是,逻辑过期时间是相对较短的,通常设置在几分钟或者几十分钟之内。

与物理过期相比,逻辑过期具有以下优点:

  • 提高了缓存的利用率:逻辑过期可以在数据失效后仍然保留数据,提高了缓存的利用率,减少了对数据源的访问次数。
  • 减少了缓存穿透的问题:即使缓存中不存在某个数据,逻辑过期也可以在一定时间内避免大量的访问请求落到数据源上,从而减轻了数据源的负担。
  • 提高了系统的性能:逻辑过期可以缩短缓存数据的更新频率,从而提高了系统的响应速度和性能。

总之,逻辑过期是一种有效的缓存策略,能够提高系统的性能和可用性。需要根据具体业务场景和数据特点选择合适的逻辑过期时间,以达到最优的缓存效果。

⭐思路

基于逻辑过期的方式解决缓存穿透问题的思路是通过在缓存中设置较短的逻辑过期时间来处理查询不存在的数据。这种方式的核心理论是将缓存和数据源之间的查询请求进行分流,减轻数据源的负担,并提高系统的响应速度。

具体来说,当一个请求到达时,先检查缓存中是否存在所需数据。如果缓存中不存在该数据,则说明可能发生了缓存穿透。为了避免直接向数据源发起查询请求,并且继续保持对数据的查询,我们通过设置逻辑过期时间来抑制该请求。也就是说,将该请求的结果设置为空,并设置一个较短的逻辑过期时间。

这样一来,在逻辑过期时间内,其他同样请求该数据的请求会继续从缓存中获取旧的空结果。这样可以避免大量请求直接访问数据源,减轻了数据源的压力。同时,在逻辑过期时间到期后,新的请求会再次触发查询数据源的操作,以更新缓存中的数据。这样可以保证缓存中的数据与数据源的一致性。

从理论上讲,基于逻辑过期的方式能够有效地处理缓存穿透问题。通过将不存在的数据也缓存起来,并设置较短的逻辑过期时间,可以在一段时间内屏蔽掉大量的查询请求,减轻了数据源的负担。而在逻辑过期时间到期后,通过更新缓存的方式保证了数据的一致性,使得后续的请求可以从缓存中获取到最新的数据。

需要注意的是,选择适当的逻辑过期时间非常重要。过长的逻辑过期时间可能导致缓存数据与实际数据不一致,而过短的逻辑过期时间则可能增加了缓存的更新频率,影响系统的性能。在实际应用中,需要根据具体业务场景和数据特点进行调整,找到一个合适的平衡点。

🌹代码

请添加图片描述

我们把数据写入Redis里面的时候,我们要设置一个逻辑过期时间

在这里插入图片描述

我们把店铺数据加入到缓存当中

在这里插入图片描述

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryById(Long id) {//逻辑过期解决缓存击穿Shop shop=queryWithLogicalExpire(id);if(shop==null){return Result.fail("店铺不存在");}//返回return Result.ok(shop);}//创建一个线程池private static final ExecutorService CACHE_REBUILD_EXECUTOR= Executors.newFixedThreadPool(10);public Shop queryWithLogicalExpire(Long id) {String key = CACHE_SHOP_KEY + ":" + id;//从redis中查询缓存String shopJson = stringRedisTemplate.opsForValue().get(key);//判断是否存在if (StrUtil.isBlank(shopJson)) {//存在,直接返回return null;}//命中//需要先把json反序列化为对象RedisData redisData = JSONUtil.toBean(shopJson, RedisData.class);JSONObject data = (JSONObject) redisData.getData();Shop shop = JSONUtil.toBean(data, Shop.class);LocalDateTime expireTime = redisData.getExpireTime();//判断缓存是否过期if (expireTime.isAfter(LocalDateTime.now())) {//未过期,直接返回店铺信息return shop;}//过期,需要缓存重建//缓存重建//获取互斥锁String lockKey = "lock:shop" + id;boolean isLock = tryLock(lockKey);//判断是否获取锁成功if (isLock) {//成功,开启独立线程,实现缓存重建CACHE_REBUILD_EXECUTOR.submit(() -> {try {//缓存重建this.saveShop2Redis(id, 30L);}catch (Exception e) {throw new RuntimeException(e);}finally {//释放锁unlock(lockKey);}});}//返回return shop;}//获取锁private boolean tryLock(String key){Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}//释放锁private void unlock(String key){stringRedisTemplate.delete(key);}public void saveShop2Redis(Long id,Long expireSeconds){//查询店铺数据Shop shop=getById(id);//封装逻辑过期时间RedisData redisData = new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusMinutes(expireSeconds));//写入redisstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY+":"+id, JSONUtil.toJsonStr(redisData));}}

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述

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

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

相关文章

Git使用手册--超级详细,自己都看哭了

Git 一.git简介 Git是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09;。 关于版本控制系统: 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统.有了它你就可以将选定的文件回溯到之前的状态&#xff0c;甚…

nodejs核心模块fs删除文件_用 NodeJS 重命名系统文件

作者&#xff1a;Nick Major翻译&#xff1a;疯狂的技术宅原文&#xff1a;https://coderrocketfuel.com/article/how-to-rename-a-system-file-using-node-js未经允许严禁转载介绍你是在 Node.js 中操作系统文件&#xff0c;并且需要一种简单的方法来以编程方式重命名文件&…

Java io流---拷贝目录

Java io流—拷贝目录 代码: package demo01;import java.io.File;public class CopyAll {public static void main(String[] args) {//拷贝源File srcFile new File("E:\\学习\\a");//拷贝目标File destFile new File("C:\\Users\\22721\\Desktop");//…

套口机跳针修理带图_套口机维修注意事项

套口机维修几点注意事项&#xff1a;首先要仔细检查、剖析套口机断线首要是什么缘由发生的断线。缝神总结以下几点与我们讨论&#xff1a;1、作业开端断线&#xff0c;即是说车工踏下踏板&#xff0c;刚开端缝就断了。缘由是榜首夹线器太紧了&#xff0c;留下的线头太短&#x…

Java io流---拷贝文件夹下的所有文件和目录

Java io流—拷贝文件夹下的所有文件和目录 代码: package demo01;import java.io.*; import java.util.TreeMap;public class CopyAll {public static void main(String[] args) {//拷贝源File srcFile new File("E:\\学习\\a");//拷贝目标File destFile new Fil…

k8s挂载目录_K8S中挂载目录引发的血案!

在kubernetes中部署前端项目(使用nginx作为服务器)的时候,遇到了一个报错,报错信息如下2019/11/19 02:16:31 [emerg] 1#1: open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:14nginx: [emerg] open() "/etc/ngi…

[LeetCode] 1. 两数之和 (Java)

[LeetCode] 1. 两数之和 (Java) 1. 题目描述 力扣两数之和传送门 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff…

tcpsyn发生在哪层_必看面试题之计算机网络:来自一位拿到了腾讯和字节双offer的大佬...

有小伙伴反映上篇文不全面&#xff0c;深觉文笔有限&#xff0c;于是&#xff0c;给大家分享一篇牛客网面上了腾讯和字节跳动的大佬的计算机网络面试相关知识点的总结。

[LeetCode] 1108. IP 地址无效化 (Java)

[LeetCode] 1108. IP 地址无效化 (Java) 1. 题目描述 力扣传送门 给你一个有效的 IPv4 地址 address&#xff0c;返回这个 IP 地址的无效化版本。 所谓无效化 IP 地址&#xff0c;其实就是用 “[.]” 代替了每个 “.”。 示例 1&#xff1a; 输入&#xff1a;address “1…

移动端web设计尺寸_移动端H5页面的设计稿尺寸大小规范

当我们在做手机端H5网页设计稿时(当然包含微信端的H5网页设计)&#xff0c;如果没有做过类似的移动端的设计&#xff0c;UI设计师和前端工程师肯定会纠结的。如果是app设计师&#xff0c;就不会那么纠结啦。那么多手机屏幕尺寸&#xff0c;设计稿应该按照哪一个尺寸作为标准尺寸…

[算法] 二叉树的DFS与BFS算法 (Java) -- 痛定思痛 彻底搞懂

二叉树的DFS与BFS算法 (Java) 1.概念 ①DFS (深度优先搜索) 维基百科读一遍 定义看完, 看一遍gif ②BFS (广度优先搜索) 维基百科读一遍 gif看一遍 2. 算法实现 二叉树节点结构: public class TreeNode {int value;TreeNode left;TreeNode right;public TreeNode(int…

mybatis返回map键值对_mybatis返回map key怎么指定

展开全部一、概述MyBatis中在查询进行select映射的时候&#xff0c;返回类型可以用resultType&#xff0c;也可以用resultMap&#xff0c;resultType是直接表示返回类型的&#xff0c;而resultMap则是对外部ResultMap的引用&#xff0c;636f7079323131333532363134313032313635…

[LeetCode] 485.最大连续 1 的个数(Java)

[LeetCode] 485.最大连续 1 的个数(Java) 1.题目描述 力扣传送门 给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 示例 1&#xff1a;输入&#xff1a;nums [1,1,0,1,1,1] 输出&#xff1a;3 解释&#xff1a;开头的两位和最后的三位都是连续 1 &…

两个音轨合并_两个双音轨mkv视频合并保持原双音轨不变 MKV怎么合并视频,合并之后仍保留MKV的双音轨...

在写文之前先说明下&#xff0c;笔者在双音轨处理方面接触不久&#xff0c;也只算是半吊子&#xff0c;离砖家级别还有些距离滴&#xff0c;若有不足的地方&#xff0c;欢迎大家补充哈。今天突然想到mkv视频合并的问题&#xff0c;就是MKV怎么合并视频&#xff0c;合并之后要保…

[LeetCode] 495. 提莫攻击 (Java)

[LeetCode] 495. 提莫攻击 (Java) 1.题目描述 在《英雄联盟》的世界中&#xff0c;有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希&#xff08;编者注&#xff1a;寒冰射手&#xff09;进入中毒状态。 当提莫攻击艾希&#xff0c;艾希的中毒状态正好持续 duration 秒…

conv2d的输入_pytorch1.0中torch.nn.Conv2d用法详解

Conv2d的简单使用torch 包 nn 中 Conv2d 的用法与 tensorflow 中类似&#xff0c;但不完全一样。在 torch 中&#xff0c;Conv2d 有几个基本的参数&#xff0c;分别是in_channels 输入图像的深度out_channels 输出图像的深度kernel_size 卷积核大小&#xff0c;正方形卷积只为单…

Tomcat内存释放不了、Tomcat内存溢出原因

公司的tomcat又挂掉了,之前挂了一次.出现以下错误,后来把tomcat的内存增大到1024 严重: Exception initializing page context java.lang.OutOfMemoryError: Java heap space 在tomcat\bin\catalina.bat的set CURRENT_DIR%cd% 前面添加 set JAVA_OPTS -Xms5…

[LeetCode] 414.第三大的数(Java)

[LeetCode] 414.第三大的数(Java) 1.题目描述 给你一个非空数组&#xff0c;返回此数组中 第三大的数 。如果不存在&#xff0c;则返回数组中最大的数。 示例 1&#xff1a;输入&#xff1a;[3, 2, 1] 输出&#xff1a;1 解释&#xff1a;第三大的数是 1 。 示例 2&#xff…

win10 4k分屏 eclipse等工具打开后按钮图标大小问题解决方案

1、打开显示设置 2、打开eclipse属性、直接上图&#xff1a;

python用海伦公式求面积_Python:平面直角坐标系下用三点求所构三角形面积

我使用了一种特殊方式&#xff0c;计算平面直角坐标系下三点所构成&#xff08;如果可行的话&#xff09;的三角形的面积。这个方法&#xff0c;不同於常见的海伦公式。设此三点坐标分别为&#xff1a;算出最大最小的 与 &#xff0c;并根据三点坐标&#xff0c;虚构出一个矩形…