Redis-实战篇-缓存击穿问题及解决方案

文章目录

  • 1、缓存击穿
  • 2、常见的解决方案有两种:
    • 2.1、互斥锁
    • 2.2、逻辑过期
    • 2.3、两种方案对比
  • 3、利用互斥锁解决缓存击穿问题
    • 3.1、ShopServiceImpl.java
    • 3.2、使用 jmeter.bat 测试高并发
  • 4、利用逻辑过期解决缓存击穿问题

1、缓存击穿

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

在这里插入图片描述

2、常见的解决方案有两种:

2.1、互斥锁

在这里插入图片描述

2.2、逻辑过期

在这里插入图片描述

2.3、两种方案对比

在这里插入图片描述

3、利用互斥锁解决缓存击穿问题

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

在这里插入图片描述

3.1、ShopServiceImpl.java

package com.hmdp.service.impl;import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import static com.hmdp.utils.RedisConstants.*;/*** <p>*  服务实现类* </p>*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic Result queryById(Long id) {String key = CACHE_SHOP_KEY + id;//1、从redis查询商铺缓存String shopJson = stringRedisTemplate.opsForValue().get(key);//2、判断是否存在if (StrUtil.isNotBlank(shopJson)) {//3、存在,直接返回Shop shop = JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//判断命中的是否是空值if (shopJson != null) {return Result.fail("店铺不存在!");}//4.实现缓存重建//4.1、获取互斥锁String lockKey = "lock:shop:" + id;Shop shop = null;try {boolean isLock = tryLock(lockKey);//4.2、判断是否获取成功if (!isLock) {//4.3、失败,则休眠并重试Thread.sleep(50);return queryById(id);}//4.4、不存在,根据id查询数据库shop = getById(id);//模拟重建延时Thread.sleep(200);//5、数据库不存在,返回错误if (shop == null) {// 将空值写入redisstringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);//返回错误信息return Result.fail("店铺不存在!");}//6、存在,写入redisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {//7、释放互斥锁unlock(lockKey);}//8、返回return Result.ok(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);}@Override@Transactionalpublic Result update(Shop shop) {Long id = shop.getId();if (id == null) {return Result.fail("店铺id不能为空");}//1、更新数据库updateById(shop);//2、删除缓存stringRedisTemplate.delete(CACHE_SHOP_KEY + id);return Result.ok();}
}

3.2、使用 jmeter.bat 测试高并发

在这里插入图片描述
在这里插入图片描述

删除redis中的缓存,开启并发测试

2024-06-26 19:48:17.421 DEBUG 19720 --- [io-8081-exec-46] com.hmdp.mapper.ShopMapper.selectById    : ==>  Preparing: SELECT id,name,type_id,images,area,address,x,y,avg_price,sold,comments,score,open_hours,create_time,update_time FROM tb_shop WHERE id=?
2024-06-26 19:48:17.422 DEBUG 19720 --- [io-8081-exec-46] com.hmdp.mapper.ShopMapper.selectById    : ==> Parameters: 1(Long)
2024-06-26 19:48:17.424 DEBUG 19720 --- [io-8081-exec-46] com.hmdp.mapper.ShopMapper.selectById    : <==      Total: 1

我们发现只查询数据库一次,证明互斥锁方案成功,并没有所有的请求都打到数据库

4、利用逻辑过期解决缓存击穿问题

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

在这里插入图片描述

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

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

相关文章

LeetCode 2741.特别的排列:状压DP

【LetMeFly】2741.特别的排列&#xff1a;状压DP 力扣题目链接&#xff1a;https://leetcode.cn/problems/special-permutations/ 给你一个下标从 0 开始的整数数组 nums &#xff0c;它包含 n 个 互不相同 的正整数。如果 nums 的一个排列满足以下条件&#xff0c;我们称它是…

<电力行业> - 《第4课:什么是电力?什么是发输变配用5环节?》

1 什么是电力&#xff1f; 我们对于平日生活中离不开的电很熟悉&#xff0c;但是电力是什么&#xff1f; 其实&#xff0c;电力就是电能作为动力的能源。电力就是我们说的电&#xff0c;不过更多了系统化。 19世纪70年代&#xff0c;电力的发明和应用掀起了第二次工业化高潮。…

关于WebSocket

WebSocket 与传统的 HTTP 协议对比 在实时通信领域&#xff0c;传统的 HTTP 协议存在以下一些问题&#xff1a; 频繁的请求和响应&#xff1a;每次通信都需要建立和关闭连接&#xff0c;带来额外的开销。高延迟&#xff1a;每次通信都需要经过多个网络层的传输&#xff0c;延…

Stm32的DMA的学习

一&#xff0c;介绍 二&#xff0c;DMA框图 三&#xff0c;DMA通道 四&#xff0c;相关HAL库函数 五&#xff0c;配置DMA 六&#xff0c;Stm32CubeMX配置 【13.1】减少CPU传输负载 DMA直接存储器访问—Kevin带你读《STM32Cube高效开发教程基础篇》_哔哩哔哩_bilibili

【鸿蒙 HarmonyOS】尺寸设置:size/layoutWeight/constraintSize

一、背景 常见尺寸&#xff1a;width&#xff08;宽度&#xff09;、height&#xff08;高度&#xff09;、padding&#xff08;内边距&#xff09;、margin&#xff08;外边距&#xff09; 主要整理下size&#xff08;设置高宽尺寸&#xff09;、layoutWeight&#xff08;对…

主干网络篇 | YOLOv5/v7 更换骨干网络之 PP-LCNet | 轻量级CPU卷积神经网络

主干网络篇 | YOLOv5/v7 更换骨干网络之 PP-LCNet | 轻量级CPU卷积神经网络&#xff1a;中文详解 1. 简介 YOLOv5 和 YOLOv7 是目前主流的目标检测算法之一&#xff0c;具有速度快、精度高的特点。但 YOLOv5 和 YOLOv7 的原始模型结构中使用的是 MobileNetV3 作为骨干网络&am…

Redis数据库(五):Redis数据库基本特性

这一节我们来介绍如何使用C语言的库来操作Redis数据库。 目录 一、hiredis的安装 1.1 下载源码 1.2 解压 1.3 进入hiredis路径下 1.4 利用makefile文件进行编译 二、接口介绍 三、C程序操作Redis代码 四、redis.conf配置文件详解 五、Redis的持久化 5.1 RDB &#x…

Compose学习记录(2)-组件状态

Compose中的状态 可组合函数可以按任意顺序频繁执行&#xff0c;对于组件中的状态需要通过特定方式保存起来。当状态发生变化时&#xff0c;它会自动触发组件UI的重组: remember{ mutableStateOf(T) } Composable fun Greeting(name: String, modifier: Modifier Modifier) {…

STM32CubeMX与RT-Thread Studio协助使用(实现点亮LED)

1创建自己的项目 1-1选择板子 1-2生成的项目 运行一下看是否创建成功 零警告零错误 2配置STM32Cude 2-1找打如图图标点击&#xff08;CubeMX的图标&#xff09; 2-2输入自己安装的路径选中exe文件 点击Browse 找到如图选中&#xff0c;在打开&#xff08;STM32CubeMX的安装路…

202406261021_二分查找2

202406261021_二分查找2 ✏随笔34. 在排序数组中查找元素的第一个和最后一个元素代码总结 69. x的平方根代码总结 367. 有效的完全平方数代码总结 (Weather::上海 ⛅多云&#xff0c;13~23℃ 良 清风徐徐&#x1f318;) ✏随笔 34. 在排序数组中查找元素的第一个和最后一个元素…

echarts 5.5.0版本下的层叠柱形图,每个值都从0开始,会有覆盖情况

需求&#xff1a; 1、每个公司&#xff0c;需要两个柱子去展示&#xff08;stack: 1是第一个柱子&#xff0c;stack:2,是第二个柱子&#xff09;&#xff1b; 2、必须每个数据都是从0开始&#xff0c;不在上一个值上累加&#xff1b; 3、鼠标滑上去的时候&#xff0c;最大值…

什么是API?如何进行API对接?

目录 一、API和API对接的定义 二、API接口的应用场景 三、为什么需要API对接 四、如何进行API对接 GET请求 POST请求 五、API对接的注意事项 在这个数字化时代&#xff0c;API像一把万能钥匙&#xff0c;让数据流动起来&#xff0c;创造出无限可能。本文旨在介绍API及其…

点云处理实战 PCL求解点云表面曲率

目录 一、什么是曲率 二、曲率计算过程 三、pcl 求解点云局部曲率 四、思考?为何曲率计算会使用协方差矩阵? 五、推荐阅读 一、什么是曲率 曲率是几何学中用来描述曲线或曲面形状变化的一个量。它反映了曲线或曲面的弯曲程度。在不同的上下文中,曲率的定义和计算方式有…

如何在Spring Boot中实现文件上传和下载

如何在Spring Boot中实现文件上传和下载 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中实现文件的上传和下载功能&…

科普:什么是 BC-404 ?全方位解读最新通缩型 NFT 标准

区块链技术飞速发展的今天&#xff0c;创新从未停歇。继 ERC-404 标准问世后&#xff0c;一个名为 BC-404 的新标准应运而生&#xff0c;为 NFT 市场带来了全新的可能性。BC-404&#xff08;Bonding Curve 404&#xff09;—基于对 ERC-404 的改进&#xff0c;加密货币中第一个…

在ROS2中蓝牙崩溃的原因分析

在ROS2中&#xff0c;如果蓝牙模块没有成功启动&#xff0c;可能的原因有几个方面&#xff1a; 1. **硬件问题**&#xff1a;首先需要确认蓝牙硬件本身是否正常工作&#xff0c;包括检查蓝牙模块是否正确连接到系统&#xff0c;以及模块是否存在物理损坏。 2. **驱动问题**&a…

三、知识库搭建

知识库搭建 1 介绍词向量向量数据库 2 使用embedding API3 数据处理数据加载数据清洗文档分割 4 搭建并使用向量数据库4.1 自定义embedding封装4.2 chroma数据库4.3 向量检索 详细代码参考&#xff1a;https://github.com/lin902/llm-application 1 介绍 词向量 词向量就是把…

logging日志级别介绍

1 日志的等级可以分为5个 从底到高分别是 debug 程序调式bug使用 info 程序正常运行 warning 发出警告 error 程序出错 critical 特别验证 程序不能运行 2 使用&#xff1a; import logging logging.debug(这是一个dug日志的信息) 3 设置logging的配置信息 创建…

RK3568平台开发系列讲解(调试篇)分析内核调用的利器 ftrace

🚀返回专栏总目录 文章目录 一. 指定 ftrace 跟踪器二、设置要 trace 的函数三、ftrace 的开关四、查看 trace五、trace-cmd 的使用六、trace-cmd 的常用选项6.1、查看可以跟踪的事件6.2、跟踪特定进程的函数调用6.3、函数过滤6.4、限制跟踪深度6.5、追踪特定事件沉淀、分享、…

MYSQL insert into select 遇到的一个错误 Truncated incorrect DOUBLE value: ‘完成‘

今日在mysql 使用insert into mysql 报错了 》》Truncated incorrect DOUBLE value: ‘完成’。 单独把select 拉出来查询没有问题&#xff0c;但是一和insert into就报错了。 这种insert into select的sql 如果用了where 条件请在条件上 完全遵从数据格式&#xff0c;&#x…