当前位置: 首页 > news >正文

Redis的缓存击穿与解决

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的Key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

Redis实战篇 | Kyle's Blog (cyborg2077.github.io) 

目录

解决方案

互斥锁

 实现

逻辑过期 

 实现


解决方案

 

互斥锁

 实现

需求:修改根据id查询商铺的业务,基于互斥锁方式来解决缓存击穿问题

 

  • 操作锁的代码

  • 核心思路就是利用redis的setnx方法来表示获取锁,如果redis没有这个key,则插入成功,返回1,如果已经存在这个key,则插入失败,返回0。在StringRedisTemplate中返回true/false,我们可以根据返回值来判断是否有线程成功获取到了锁

 ShopServiceImpl

 public Shop queryWithMutex(Long id) {//先从Redis中查,这里的常量值是固定的前缀 + 店铺idString shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);//如果不为空(查询到了),则转为Shop类型直接返回if (StrUtil.isNotBlank(shopJson)) {Shop shop = JSONUtil.toBean(shopJson, Shop.class);return shop;}if (shopJson != null) {return null;}Shop shop = null;try {//否则去数据库中查boolean flag = tryLock(LOCK_SHOP_KEY + id);if (!flag) {Thread.sleep(50);return queryWithMutex(id);}//查不到,则将空值写入Redisshop = getById(id);if (shop == null) {stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "", CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//查到了则转为json字符串String jsonStr = JSONUtil.toJsonStr(shop);//并存入redis,设置TTLstringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, jsonStr, CACHE_SHOP_TTL, TimeUnit.MINUTES);//最终把查询到的商户信息返回给前端} catch (InterruptedException e) {throw new RuntimeException(e);} finally {unLock(LOCK_SHOP_KEY + id);}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);}

 

逻辑过期 

直接在redis中设计一个永久的热点key,当发现逻辑时间已过期则采用类似互斥锁方式解决缓存击穿 

 

 实现

  • 需求:根据id查询商铺的业务,基于逻辑过期方式来解决缓存击穿问题
  • 思路分析:当用户开始查询redis时,判断是否命中
    • 如果没有命中则直接返回空数据,不查询数据库
    • 如果命中,则将value取出,判断value中的过期时间是否满足
      • 如果没有过期,则直接返回redis中的数据
      • 如果过期,则在开启独立线程后,直接返回之前的数据,独立线程去重构数据,重构完成后再释放互斥锁

 

封装数据:因为现在redis中存储的数据的value需要带上过期时间,此时要么你去修改原来的实体类,要么新建一个类包含原有的数据和过期时间

  • 步骤一
  • 这里我们选择新建一个实体类,包含原有数据(用万能的Object)和过期时间,这样对原有的代码没有侵入性
@Data
public class RedisData<T> {private LocalDateTime expireTime;private T data;
}
  • 步骤二
  • 在ShopServiceImpl中新增方法
public void saveShop2Redis(Long id, Long expirSeconds) {Shop shop = getById(id);RedisData redisData = new RedisData();redisData.setData(shop);redisData.setExpireTime(LocalDateTime.now().plusSeconds(expirSeconds));stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(redisData));
}
  • 步骤三:正式代码
    正式代码我们就直接照着流程图写就好了
//这里需要声明一个线程池,因为下面我们需要新建一个现成来完成重构缓存
private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);@Override
public Shop queryWithLogicalExpire(Long id) {//1. 从redis中查询商铺缓存String json = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);//2. 如果未命中,则返回空if (StrUtil.isBlank(json)) {return null;}//3. 命中,将json反序列化为对象RedisData redisData = JSONUtil.toBean(json, RedisData.class);//3.1 将data转为Shop对象JSONObject shopJson = (JSONObject) redisData.getData();Shop shop = JSONUtil.toBean(shopJson, Shop.class);//3.2 获取过期时间LocalDateTime expireTime = redisData.getExpireTime();//4. 判断是否过期if (LocalDateTime.now().isBefore(expireTime)) {//5. 未过期,直接返回商铺信息return shop;}//6. 过期,尝试获取互斥锁boolean flag = tryLock(LOCK_SHOP_KEY + id);//7. 获取到了锁if (flag) {//8. 开启独立线程CACHE_REBUILD_EXECUTOR.submit(() -> {try {this.saveShop2Redis(id, LOCK_SHOP_TTL);} catch (Exception e) {throw new RuntimeException(e);} finally {unlock(LOCK_SHOP_KEY + id);}});//9. 直接返回商铺信息return shop;}//10. 未获取到锁,直接返回商铺信息return shop;
}

 

相关文章:

Redis的缓存击穿与解决

缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的Key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 Redis实战篇 | Kyles Blog (cyborg2077.github.io) 目录 解决方案 互斥锁 实现 逻辑过期 实现 解决方案…...

网络层 IP协议【计算机网络】【协议格式 || 分片 || 网段划分 || 子网掩码】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;Linux_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;前提 二&…...

Python学习笔记14:进阶篇(三)。类的终结篇,类的导入和模块的导入。

前言 这篇文章属于类知识的最后一篇&#xff0c;带一点点其他知识&#xff0c;学习内容来自于Python crash course。 关注我私信发送Python crash course&#xff0c;分享一份中文版PDF。 类的导入 在学习的时候&#xff0c;包括之前&#xff0c;我都是在一个文件中把所有代…...

C++ lambda表达式举例

C lambda表达式 Lambda表达式是一种简洁的方式来创建匿名函数&#xff0c;可以直接在函数调用的地方定义&#xff0c;主要用于简化代码。 Lambda表达式的基本语法如下&#xff1a; [capture](parameters) -> return_type {// function body };示例1&#xff1a;基本用法 …...

持续总结中!2024年面试必问 20 道设计模式面试题(五)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道设计模式面试题&#xff08;四&#xff09;-CSDN博客 九、请解释代理模式&#xff08;Proxy Pattern&#xff09;及其类型。 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构设计模式&#xff0c…...

嵌入式面经111题答案汇总(含技术答疑)_嵌入式项目源码分享

111道嵌入式面试题答案汇总专栏链接&#xff08;承诺免费技术答疑&#xff09; --> 《嵌入式/C面试题解析大全》 1、简介 本人是2020年毕业于广东工业大学研究生&#xff1a;许乔丹&#xff0c;有国内大厂CVTE和世界500强企业工作经验&#xff0c;整理超全面111道嵌入式面试…...

鸿蒙开发通信与连接:【@ohos.connectedTag (有源标签)】

有源标签 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import connectedTag from ohos.connectedTag;connectedTag.init init(): boolean 初始化有源标签芯片。 需要权限&#…...

在线编程工具

1.C语言在线编程 https://www.jyshare.com/compile/11/ 2.java在线编程 https://www.w3cschool.cn/tryrun/runcode1?langjava 3.Python在线编程 https://www.python123.io/index/playground/python?ivk_sa1024320u...

NSSCTF中的[WUSTCTF 2020]朴实无华、[FSCTF 2023]源码!启动! 、[LitCTF 2023]Flag点击就送! 以及相关知识点

目录 [WUSTCTF 2020]朴实无华 [FSCTF 2023]源码&#xff01;启动! [LitCTF 2023]Flag点击就送&#xff01; 相关知识点 1.intval 绕过 绕过的方式&#xff1a; 2.session伪造攻击 [WUSTCTF 2020]朴实无华 1.进入页面几乎没什么可用的信息&#xff0c;所以想到使用dis…...

Vue49-props属性

一、当同一个组件标签被使用多次 因为data属性写的是函数形式&#xff01; 二、需求&#xff1a;老王也想用<Student>组件&#xff0c;但是需要动态把老王想要的值传进来。 2-1、使用props属性接收参数 使用props属性&#xff0c;接收的这三个参数&#xff0c;是被保存在…...

CVE-2020-1957 漏洞复现

先声明一下&#xff0c;免杀还是会更的&#xff0c;不过中间可能会穿插一下渗透的内容&#xff01;&#xff01;&#xff01; 踩坑点&#xff1a; 在一开始翻阅了CSDN之后&#xff0c;发现不同文章之间存在出入&#xff0c;于是最后去了CVE的官方文档&#xff0c;和参考一些国…...

网工内推 | 中国电信、香港宽频系统工程师,CCIE认证优先,最高年薪25w

01 中国电信股份有限公司浙江分公司 &#x1f537;招聘岗位&#xff1a;系统架构师 &#x1f537;岗位职责&#xff1a; 1、做好客户网络和信息安全产品的解决方案支撑、交付及后续运营维护&#xff0c;做好相关产数项目的支撑。 2、根据信息安全管理要求&#xff0c;负责客户…...

LLVM后端 td文件 tablegen 模式匹配 寄存器 指令集 calling convention

目录 一、寄存器 1.1 寄存器定义 1.2 寄存器分类 二、指令集 2.1 指令集定义 2.2 模式匹配 2.2.1 PatFrags与PatFrag 2.2.2 OutPatFrag 2.2.3 PatLeaf 2.2.4 ImmLeaf 2.2.5 IntImmLeaf和FPImmLeaf 2.2.6 Pat 2.2.7 ComplexPattern 2.3 指令合法化 2.3.1 Promote…...

嵌入式交叉编译:frp

参考 LINUX FRP下载编译_linux编译frpc-CSDN博客 编译 make -f Makefile.cross-compiles 检查 $ make -f Makefile.cross-compiles Build darwin-amd64... Build darwin-amd64 done Build darwin-arm64... Build darwin-arm64 done Build freebsd-amd64... Build freebsd-…...

SpringBoot实现的大文件上传

前言 大文件分片上传和断点续传是为了解决在网络传输过程中可能遇到的问题&#xff0c;以提高文件传输的效率和稳定性。 首先&#xff0c;大文件分片上传是将大文件分割成较小的片段进行上传。这样做的好处是可以减少单个文件的传输时间&#xff0c;因为较小的文件片段更容易快…...

【Python高级编程】用 Matplotlib 绘制迷人的图表

用 Matplotlib 绘制迷人的图表 引言 Matplotlib 是 Python 中广泛使用的绘图库&#xff0c;用于创建各种图表和可视化。本文将逐步指导您使用 Matplotlib 绘制基本图表&#xff0c;包括折线图、条形图和散点图。 安装 Matplotlib 使用 pip 安装 Matplotlib&#xff1a; pi…...

【UML用户指南】-19-对基本行为建模-用例图

目录 1、组成结构 2、表示法 3、一般用法 3.1、对主题的语境建模 3.2、对主题的需求建模 4、常用建模技术 4.1、对系统的语境建模 4.1.1、设计过程 4.2、对系统的需求建模 4.2.1、设计过程&#xff1a; 5、正向工程 UML 中的用例图是对系统的动态方面建模的 5 种图之…...

mysql密码过期的修改(Your password has expired. ..)

参考文章&#xff1a;mysql密码过期的修改方法&#xff08;your password has expired&#xff09;_我是知青-RuoYi 若依 (csdn.net) 问题&#xff1a;Your password has expired. To log inyou must change it using a clientthat supports expired passwords. 解决方式&…...

vivado SLR

描述 超级逻辑区&#xff08;SLR&#xff09;是包含在堆叠硅中的单个FPGA芯片 互连&#xff08;SSI&#xff09;设备。堆叠式硅互连&#xff08;SSI&#xff09;技术使用无源硅 具有微凸块和硅通孔&#xff08;TSV&#xff09;的内插器&#xff0c;用于组合多个FPGA管芯 切片&a…...

【CSS】深入了解圆角属性border-radius

border-radius 是 CSS 中的一个非常有用的属性&#xff0c;它允许你创建具有圆角边框的元素。这个属性可以应用于一个元素的四个角&#xff0c;或者分别应用于每个角。下面我们将深入了解 border-radius 的使用方法和一些高级技巧。 基本用法 你可以通过为 border-radius 指定…...

LabVIEW与C#的区别及重新开发自动测试程序的可行性分析

LabVIEW和C#是两种广泛使用的编程语言&#xff0c;各自有不同的应用领域和特点。本文将详细比较LabVIEW与C#在自动测试程序开发中的区别&#xff0c;并分析将已完成的LabVIEW自动测试程序重新用C#开发的合理性。本文帮助评估这种转换的必要性和潜在影响。 LabVIEW与C#的区别 开…...

人工智能—美国加利福尼亚州房价预测实战

引言 在当今快速发展的房地产市场中&#xff0c;房价预测已成为一个至关重要的领域。它不仅关系到投资者的决策&#xff0c;也直接影响到普通购房者的生活质量。特别是在美国加利福尼亚州&#xff0c;这个以其高房价和房地产市场的波动性而闻名的地方&#xff0c;准确的房价预…...

python pandas处理股票量化数据:笔记2

有一个同学用我的推荐链接注册了tushare社区帐号https://tushare.pro/register?reg671815&#xff0c;现在有了170分积分。目前使用数据的频率受限制。不过可以在调试期间通过python控制台获取数据&#xff0c;将数据保存在本地以后使用不用高频率访问tushare数据接口&#xf…...

enum库

Python enum 模块教程 enum 是 Python 3.4 引入的一个模块&#xff0c;用于定义枚举类型。枚举类型是一种特殊的数据类型&#xff0c;由一组命名的值组成&#xff0c;这些值称为枚举成员。使用 enum 可以提高代码的可读性和可维护性&#xff0c;特别是在处理一组相关的常量值时…...

【CT】LeetCode手撕—141. 环形链表

目录 题目1- 思路2- 实现⭐141. 环形链表——题解思路 3- ACM实现 题目 原题连接&#xff1a;141. 环形链表 1- 思路 模式识别 模式1&#xff1a;判断链表的环 ——> 快慢指针 思路 快指针 ——> 走两步慢指针 ——> 走一步判断环&#xff1a;若快慢相遇则有环&a…...

python,自定义token生成

1、使用的包PyJWT来实现token生成 安装&#xff1a;pip install PyJWT2.8.0 2、使用例子&#xff1a; import jwt import time pip install pyJWT2.8.0 SECRET_KEY %^ES*E&Ryurehuie9*7^%$#$EDFGHUYTRE#$%^&%$##$RTYGHIK DEFAULT_EXP 7 * 24 * 60def create_token(…...

小米SU7遇冷,下一代全新车型被官方意外曝光

不知道大伙儿有没有发现&#xff0c;最近小米 SU7 热度好像突然之间就淡了不少&#xff1f; 作为小米首款车型&#xff0c;SU7 自上市以来一直承载着新能源轿车领域流量标杆这样一个存在。 发售 24 小时订单量破 8 万&#xff0c;2 个月后累计交付破 2 万台。 看得出来限制它…...

JavaScript 函数与事件

1. JavaScript自定义函数 语法&#xff1a; function 函数名&#xff08;参数列表&#xff09;{ 方法体; } 在函数被调用时&#xff0c;一个 arguments 对象就会被创建&#xff0c;它只能使用在函数体中&#xff0c;以数组的形式来管理函数的实际…...

Qt 焦点系统关键点总结

1.1 焦点窗口 指的是当前时刻拥有键盘输入的窗口。 Qt提供了如下接口&#xff0c;用于设置窗口是否是”可获取焦点“窗口&#xff1a; void QWidget::setFocusPolicy(Qt::FocusPolicy policy); Qt::FocusPolicy Qt::TabFocus 与焦点链相关&#xff0c;详解见下一…...

SpringBoot+Maven项目的配置构建

文章目录 1、application.properties2、pom.xml 1、application.properties 也可使用yml yaml #静态资源 spring.mvc.static-path-pattern/images/** #上传文件大小设置 spring.http.multipart.max-file-size10MB spring.http.multipart.max-request-size10MBspring.mvc.path…...

网站后台可视化编辑/济南百度推广优化

1.文章概述在项目debug时发现log中经常不断的触发lowemeory killer(以后简称LMK)机制去kill掉一些进程&#xff0c;后查明是在sharefolder时候配置init.qcom.post_boot.sh对LMK门限值设定出现遗漏&#xff0c;导致阀值过高&#xff0c;以至于LMK长期被触发&#xff0c;并占用了…...

wordpress能批量上传图片么/线上推广策划方案范文

设计数据库之前&#xff0c;需要绘制ER图&#xff0c;通过ER图创建出对应的表结构&#xff0c;后期可能需要修改表结构&#xff0c;那么还需要修改ER图&#xff0c;甚至重写&#xff0c;很麻烦&#xff0c;浪费大量时间。 powerdesigner的好处是&#xff1a;在创建好ER图之后&a…...

网站制作企业首页/短视频营销方式有哪些

这是python数据分析入门的的第2篇文章&#xff1a;第一篇文章&#xff1a;思里皮&#xff1a;Python软件安装及基础数据类型本文文章结构条件判断循环函数模块数据结构条件判断&#xff1a;单条件判断多条件判断级联的else if&#xff0c;elif是其缩写。循环&#xff1a;for 循…...

wordpress 文章字体/cfa一级看多久两分钟

我有一个在经纬度网格上的数据集。我需要从这个数据集中选择一个近乎完美的“矩形”覆盖北美。某物&#xff0c;但位于北美上空&#xff1a;1。我如何选择纬度和经度&#xff1f;因为经度向两极靠拢&#xff0c;所以我需要更多的经度往北。在这是我的拙劣和可能不正确的尝试。我…...

建设外贸型网站/百度知道

前言 在日常开发工作中&#xff0c;我们往往需要自己去构建各种数据表所对应的持久化对象&#xff08;PO&#xff09;、用于操作数据库的接口&#xff08;DAO&#xff09;以及跟 DAO 所绑定的对应 XML。这都是一些重复性的操作&#xff0c;不需要多大技术含量&#xff0c;这时…...

建设企业网站企业网上银行官网官方/广告联盟点击赚钱平台

题目&#xff1a;原题链接&#xff08;中等&#xff09; 标签&#xff1a;SQL 解法时间复杂度空间复杂度执行用时Ans 1 (Python)341ms (42.83%)Ans 2 (Python)Ans 3 (Python) 解法一&#xff1a; SELECT Name FROM Candidate WHERE id IN(SELECT CandidateIdFROM (SELECT Ca…...