Redis9:商户查询缓存3

欢迎来到“雪碧聊技术”CSDN博客!

在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目心得。

让我们一同在Java的广阔天地中遨游,携手提升技术能力,共创美好未来!感谢您的关注与支持,期待在“雪碧聊技术”与您共同成长!

目录

一、缓存雪崩

1、什么是缓存雪崩?

2、解决方案

二、缓存击穿

1、什么是缓存击穿?

2、解决方案

①互斥锁

②逻辑过期

3、对比两种方案

4、案例:基于“互斥锁”,解决缓存击穿问题

​编辑

①如何实现互斥锁呢?

②编写代码

③重启项目,使用Jmeter工具测试该后端接口

5、案例:基于“逻辑过期”,解决缓存击穿问题


一、缓存雪崩

1、什么是缓存雪崩?

缓存雪崩:是指在同一时段,大量的缓存key同时失效或者Redis服务宕机,导致大量请求打到数据库,带来巨大压力。

2、解决方案

二、缓存击穿

1、什么是缓存击穿?

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

        举例:热点key的TTL突然到期了,线程1从redis中没命中,然后去数据库查询,并将数据重新写会redis(由于该热点key的缓存重建业务较复杂,因此重建时间比较久),在重建期间,由于该热点key是高并发的,因此此时无数线程请求该key,redis没命中,于是这些请求都打到数据库,导致数据库压力巨大。

2、解决方案

①互斥锁

核心思想:线程1发现redis不存在该热点key,于是获取互斥锁,然后查询数据库并重建该缓存,等把该热点key的缓存成功写到了redis中,才会释放这个互斥锁。这期间,其他线程,查询redis也没命中,于是也尝试获取互斥锁,但是获取失败了(因为互斥锁被线程1占用),于是无法进行查询数据库并重建缓存的动作,于是只能等待。等到线程1重建好缓存,才能命中。

优点:缓存和数据库,是数据一致的。

缺点:其他线程需要等待,导致性能不佳(服务可用性差)。

②逻辑过期

核心思想:往redis存数据时,我就不设置TTL,于是该热点key永远不会过期,因此不可能出现热点key失效的现象。

但是为了保证缓存、数据库的数据一致性,因此还是要往热点key的value当中添加一个逻辑过期时间,每次访问该热点缓存时,都要主动判断是否过期,如果过期,就获取互斥锁,然后开启一个新线程(等于叫来一个帮手),帮我去完成缓存重建的动作,我自己这个线程还是返回旧的缓存,这样的确有点数据不一致,但是也无伤大雅。

优点:无需等待,性能好(服务可用性好)。

缺点:导致轻微的数据不一致问题。

3、对比两种方案

综上:这两种方式的数据一致性、服务可用性(性能)不可兼得。

一致性和可用性的抉择,也是分布式系统里面,常常面临的一个问题。

这两种,也没有孰优孰劣,应当根据应用场景来进行抉择。

4、案例:基于“互斥锁”,解决缓存击穿问题

①如何实现互斥锁呢?

我们此处借助redis的机制,来实现互斥锁。

也就是,我们获取互斥锁时,就执行setnx lock 1,即:向redis中,添加一个key为lock,value为1的键值对;释放互斥锁时,就执行del lock,即:将key为lock的数据删除。

②编写代码

先编写获取、释放互斥锁的方法。

注意:redis中的setnx命令,对应stringRedisTemplate中的setIfAbsent方法。

    //自定义方法:获取互斥锁private boolean tryLock(String key){Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);//防止Boolean自动拆箱成boolean时出现空指针异常}//自定义方法:释放互斥锁private void unlock(String key){stringRedisTemplate.delete(key);}

编写“互斥锁”解决缓存击穿的代码(带*号的,是本次要学的)

    @Overridepublic Result queryById(Long id) {String key = CACHE_SHOP_KEY + id;//1、从Redis中查询商铺缓存String shopJson = stringRedisTemplate.opsForValue().get(key);//2、判断redis是否存在if(StrUtil.isNotBlank(shopJson)){//3、存在,则直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//判断命中的是否是空值if(shopJson != null && shopJson.equals("")){//返回一个错误信息return Result.fail("店铺信息不存在!防止缓存穿透!");}//4、redis中不存在,进行缓存重建 *//4.1获取互斥锁 *String lockKey = "lock:shop:"+id;Shop shop = null;try {boolean isLock = tryLock(lockKey);//4.2判断是否获取成功 *if(!isLock){//4.3失败,则休眠并重试查询redis *Thread.sleep(50);return queryById(id);//递归本方法,表示重新查询redis}//4.4成功,根据id查询数据库 *shop = getById(id);//该方法,来自mybatisPlus//模拟重建缓存的延时 *Thread.sleep(200);//5、数据库也不存在,返回错误 *if(shop == null){//将空值写入redisstringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail("店铺不存在!");}//6、数据库中存在,则写入redis,并返回给前端 *stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {//7、释放互斥锁 *unlock(lockKey);}if(shop==null){ //*return Result.fail("店铺不存在!");}//8、返回return Result.ok(shop);}

③重启项目,使用Jmeter工具测试该后端接口

可见此时没毛病,使用“互斥锁”的方式,成功解决了“缓存击穿”的问题。

5、案例:基于“逻辑过期”,解决缓存击穿问题

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

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

相关文章

解锁函数的魔力:Python 中的多值传递、灵活参数与无名之美

文章目录 前言📖一、多值返回📚1.1 多值返回的概念📚1.2 工作原理📚1.3 应用场景📜总结 📖二、 多种参数传递形式📚2.1 位置参数(Positional Arguments)📚2.2…

若依框架-添加测试类-最新

1、在【ruoyi-admin】的pom.xml下添加依赖 <!-- 单元测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><scope>test</scope></dependency><dependency>…

初识网络编程TCP/IP

目录 前言相关名词解释应用层协议——HTTP传输层协议socketTCP帧头格式三次握手、四次挥手 UDPTCP的socket实现 参考博文 前言 刚碰到网络编程&#xff0c;会出现一堆协议、概念、这层次那技术的&#xff0c;头都大了&#xff0c;还是得总结总结…… 相关名词解释 ✨✨网络…

【C++课程学习】:继承(上)(详细讲解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 一.继承的概念和定义 &#x1f384;继承的概念&#xff1a; &#x1f384;继承的定义&#xff1a; …

Linux笔记之pandoc实现各种文档格式间的相互转换

Linux笔记之pandoc实现各种文档格式间的相互转换 code review! 文章目录 Linux笔记之pandoc实现各种文档格式间的相互转换1.安装 Pandoc2.Word转Markdown3.markdown转html4.Pandoc 支持的一些常见格式4.1.输入格式4.2.输出格式 1.安装 Pandoc sudo apt-get install pandoc # …

封装的数字滚动组件的实现代码

效果&#xff1a; 学习啦&#xff1a; Vue 是一个渐进式框架&#xff0c;鼓励通过组件化来构建应用&#xff0c;其组件化优势&#xff1a; 代码复用&#xff1a;不同的视图和功能被封装成独立的组件&#xff0c;便于复用。易于维护&#xff1a;每个组件职责单一、耦合度低&…

Kafka面试题解答(二)

1.怎么尽可能保证 Kafka 的可靠性 kafka是可能会出现数据丢失问题的&#xff0c;Leader维护了一个动态的in-sync replica set&#xff08;ISR&#xff09;&#xff0c;意为和 Leader保持同步的FollowerLeader集合(leader&#xff1a;0&#xff0c;isr:0,1,2)。 如果Follower长…

分块——最为优雅的暴力

在信息学竞赛中&#xff0c;常常会遇到一些区间修改或区间查询的题目&#xff0c;如果直接敲暴力的话&#xff0c;时间复杂度是 O ( n m ) O(nm) O(nm) 可能会超时&#xff0c;如果写树状数组或线段树的话&#xff0c;又有一点复杂&#xff0c;不易理解&#xff0c;那么这时候…

w~视觉~合集20~SAM

我自己的原文哦~ https://blog.51cto.com/whaosoft/12500982 #SAM 今天&#xff0c;Meta发布史上首个图像分割基础模型SAM&#xff0c;将NLP领域的prompt范式引进CV&#xff0c;让模型可以通过prompt一键抠图。网友直呼&#xff1a;CV不存在了! 就在刚刚&#xff0c;Meta AI…

Halcon resistor.hedv 使用多个对焦级别提取深度

depth_from_focus * Extract depth using multiple focus levels * 使用多个对焦级别提取深度 Names : [] * 初始化一个空数组&#xff0c;用于存储图像名称 dev_close_window () * 关闭当前打开的图像窗口 for i : 1 to 10 by 1 * 循环开始&#xff0c;从1到10 …

qt QTreeWidgetItem详解

1、概述 QTreeWidgetItem 是 Qt 框架中的一个类&#xff0c;专门用于在 QTreeWidget&#xff08;一个基于项的树形视图&#xff09;中表示单个节点&#xff08;或称为项&#xff09;。QTreeWidget 继承自 QAbstractItemView&#xff0c;而 QTreeWidgetItem 则作为树中的一个节…

三.Linux用户和用户管理

前言&#xff1a;Linux系统是一个多用户多任务的分时操作系统&#xff0c;任何一个要使用资源的都必须向系统管理员申请一个账户&#xff0c;然后通过这个账户的身份进入系统。 一.此次目的 用户账号的添加、删除与修改。 用户口令的管理。 用户组的管理。 二.用户账号的添加…

SpringBoot技术栈:构建高效共享汽车系统

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

【笔记】扩散模型(九):Imagen 理论与实现

论文链接&#xff1a;Photorealistic Text-to-Image Diffusion Models with Deep Language Understanding 非官方实现&#xff1a;lucidrains/imagen-pytorch Imagen 是 Google Research 的文生图工作&#xff0c;这个工作并没有沿用 Stable Diffusion 的架构&#xff0c;而是级…

css:基础

前言 我们之前其实也可以写出一个看起来算是一个网页的网页&#xff0c;为什么我们还要学css&#xff1f; CSS&#xff08;Cascading Style Sheets&#xff09;也叫层叠样式表&#xff0c;是负责美化的&#xff0c;我们之前说html就是一个骨架&#xff0c;css就可以用来美化网…

[全网最细数据结构完整版]第七篇:3分钟带你吃透队列

目录 1->队列的概念及结构 2->队列的实现 2.1定义队列基本结构 struct QueueNode 和 struct Queue 2.2队列初始化函数 QueueInit 函数 2.3队列销毁函数 QueueDestroy 函数 2.4队列插入数据函数 QueuePush 函数 2.5判断队列是否为空,空返回true,非空返回false 2.6队列删…

Android笔记(三十五):用责任链模式封装一个App首页Dialog管理工具

背景 项目需要在首页弹一系列弹窗&#xff0c;每个弹窗是否弹出都有自己的策略&#xff0c;以及哪个优先弹出&#xff0c;哪个在上一个关闭后再弹出&#xff0c;为了更好管理&#xff0c;于是封装了一个Dialog管理工具 效果 整体采用责任链模块设计&#xff0c;控制优先级及弹…

掌握软件组件/单元测试中的这些术语,你就算正式入门了

上篇干货&#xff0c;和大家分享了软件测试的几个级别&#xff0c;在【组件/单元测试】当中&#xff0c;涉及不少名词术语。从之前的学员学习过程来看&#xff0c;这里比较容易出现概念混乱&#xff0c;进而导致面试过程中频频翻车&#xff0c;所以有必要在这里单独拎出来和大家…

html的week控件 获取周(星期)的第一天(周一)和最后一天(周日)

html的week控件 获取周(星期)的第一天(周一)和最后一天(周日) <input type"week" id"week" class"my-css" value"ViewBag.DefaultWeek" /><script> function PageList() { var dateStrin…

【主机游戏】艾尔登法环游戏攻略

艾尔登法环&#xff0c;作为一款备受好评但优化问题频发的游戏&#xff0c;就连马斯克都夸过 今天介绍一下这款游戏 https://pan.quark.cn/s/24760186ac0b 角色升级 在《艾尔登法环》中&#xff0c;角色升级需要找到梅琳娜。你可以在关卡前废墟的营地附近&#xff0c;风暴关…