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 {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public 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) {
                // 将空值写入redis
                stringRedisTemplate.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);
        }

        //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
    @Transactional
    public 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查询商铺的业务,基于逻辑过期方式来解决缓存击穿问题

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

半个月从几十升粉到500(发红包喽)

目录 1. 背景2. 涨粉秘籍2.1 持续创作高质量内容2.1.1 保持频率2.1.2 技术文章为主2.1.3 图文并茂 2.2 积极参与社区活动2.2.1 社区分享2.2.2 发文活动 2.3 互动与建立信任2.3.1 与读者互动2.3.2 红包互动2.3.3 动态分享 2.4 标题与内容的优化2.4.1 标题吸引2.4.2 内容实用 2.5…

【C++】C++ 超市会员卡管理系统(面向对象)(源码+数据)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

【从零开始学架构 架构基础】五 架构设计的复杂度来源:低成本、安全、规模

架构设计的复杂度来源其实就是架构设计要解决的问题&#xff0c;主要有如下几个&#xff1a;高性能、高可用、可扩展、低成本、安全、规模。复杂度的关键&#xff0c;就是新旧技术之间不是完全的替代关系&#xff0c;有交叉&#xff0c;有各自的特点&#xff0c;所以才需要具体…

解决idea中git无法管理项目中所有需要管理的文件

点击文件->设置 选择版本控制—>目录映射 点击加号 设置整个项目被Git管理

springboot助农电商系统-计算机毕业设计源码08655

摘要 近年来&#xff0c;电子商务的快速发展引起了行业和学术界的高度关注。基于移动端的助农电商系统旨在为用户提供一个简单、高效、便捷的农产品购物体验&#xff0c;它不仅要求用户清晰地查看所需信息&#xff0c;而且还要求界面设计精美&#xff0c;使得功能与页面完美融…

【GPU虚拟化到池化技术深度分析 2024】

文末有福利&#xff01; 随着大模型的兴起&#xff0c;对GPU算力的需求越来越多&#xff0c;而当前现实情况使企业往往受限于有限的GPU卡资源&#xff0c;即便进行了虚拟化&#xff0c;往往也难以充分使用GPU卡资源或持续使用资源。为解决GPU算力资源不均衡等问题&#xff0c;…

国标GB/T 28181详解:国标GBT28181-2022第三方呼叫控制的视音频文件下载流程

目录 一、定义 1、国标GB/T 28181 2、第三方呼叫控制的视音频文件下载流程 二、作用 1、提供有效的数据回顾机制 2、增强监控系统的功能性 3、保障数据传输与存储的可靠性 4、实现精细化的操作与控制 5、促进监控系统的集成与发展 6、提供清晰的信令流程和操作规范 三…

驱动开发:配置Visual Studio驱动开发环境

100编程书屋_孔夫子旧书网 配置驱动开发环境配置驱动开发模板配置驱动双机调试 在正式开始驱动开发之前&#xff0c;需要自行搭建驱动开发的必要环境&#xff0c;首先我们需要安装Visual Studio 2013这款功能强大的程序开发工具&#xff0c;在课件内请双击ISO文件并运行内部的…

基于web的产品管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于web的产品管理系统,java项目。 ecli…

5G RAN

两个entity&#xff1a;NodeB、UE entity之间传输数据的东东 entity内部的流水线岗位&#xff1a;L3/L2/L1 岗位之间是消息交互/信令交互

阿里云centos7.9 挂载数据盘到 www目录

一、让系统显示中文 参考&#xff1a;centos7 怎么让命令行显示中文&#xff08;英文-&#xff1e;中文&#xff09;_如何在命令行中显示中文-CSDN博客 1、输入命令&#xff1a;locale -a |grep "zh_CN" 可以看到已经存在了中文包 2、输入命令&#xff1a;sudo vi…

在Clion使用CubeMX Stm32的步骤

Step1 准备软件&#xff0c;安装环境&#xff1a; 1. cubemx v6.5.0&#xff08;可以兼容以前版本的project&#xff09; https://www.st.com.cn/zh/development-tools/stm32cubemx.html STM32CubeMX 默认安装目录, 6.5版本可以兼容老版本 C:\Program Files\STMicroelectroni…

Golang | Leetcode Golang题解之第199题二叉树的右视图

题目&#xff1a; 题解&#xff1a; /** 102. 二叉树的递归遍历*/ func levelOrder(root *TreeNode) [][]int {arr : [][]int{}depth : 0var order func(root *TreeNode, depth int)order func(root *TreeNode, depth int) {if root nil {return}if len(arr) depth {arr a…

3D Web轻量引擎HOOPS Web Platform赋能AEC行业数字化,高效渲染与多格式支持!

在建筑、工程和施工&#xff08;AEC&#xff09;行业&#xff0c;数字化转型和高效协作正变得越来越重要。为应对日益复杂的项目需求和不断提升的质量标准&#xff0c;AEC企业需要一种强大的工具来实现高效的3D可视化和数据管理。HOOPS Web Platform作为一款综合性3D开发平台&a…

金融科技如何多角度助力小微企业融资

一、引言 在全球化与数字化交织的时代背景下&#xff0c;金融科技&#xff08;FinTech&#xff09;作为新兴力量&#xff0c;正逐步改变传统的金融业态&#xff0c;尤其在助力小微企业融资方面&#xff0c;金融科技展现出了多元化的价值和优势。本文将从不同角度探讨金融科技如…

python操作elasticsearch

1、安装 首先&#xff0c;确保你已经安装了elasticsearch库。如果没有安装&#xff0c;可以使用pip进行安装&#xff1a; pip install elasticsearch 如下&#xff1a; 2、测试是否联通 输入 python 进入交互模式。然后依次输入一下命令。 from elasticsearch import Elas…

uniapp启动页面鉴权页面闪烁问题

在使用uni-app开发app 打包完成后如果没有token&#xff0c;那么就在onLaunch生命周期里面判断用户是否登录并跳转至登录页。 但是在app中页面会先进入首页然后再跳转至登录页&#xff0c;十分影响体验。 处理方法&#xff1a; 使用plus.navigator.closeSplashscreen() 官网…

Nginx网站服务详解(设置并发数、实现不同虚拟主机等)

一、nginx的最大并发数设置已经状态收集模块 [root192 nginx]# cat nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/user ngin…

【仪器仪表】为什么要对线材做摇摆测试?

在工作中,我们可能会看到下图所示的机器。它就是线材弯折试验机,又叫线材弯折摇摆试验机、插头引线弯折试验机等。 线缆生产厂家和质检部门对电源线、DC线进行弯曲试验都需要这样的仪器,以便验证线缆是否符合设计标准。 线材弯折试验的作用 线材弯折试验机是线材的一种质检…

谷粒商城-个人笔记(集群部署篇一)

前言 ​学习视频&#xff1a;​Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强​学习文档&#xff1a; 谷粒商城-个人笔记(基础篇一)谷粒商城-个人笔记(基础篇二)谷粒商城-个人笔记(基础篇三)谷粒商城-个人笔记(高级篇一)谷粒商城-个…