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

Redis:缓存击穿

缓存击穿(热点key): 部分key(被高并发访问且缓存重建业务复杂的)失效,无数请求会直接到数据库,造成巨大压力

1.互斥锁:可以保证强一致性

      线程一:未命中之后,获取互斥锁,再查询数据库重建缓存,写入缓存,释放锁

      线程二:查询未命中,未获得锁(已由线程一获得),等待一会,缓存命中

互斥锁实现方式:redis中setnx key value:改变对应key的value,仅当value不存在时执行,以此来实现互斥锁,防止出现锁得不到释放,设置有效期

public Shop queryWithMutex(Long id) throws InterruptedException {Shop shop;//实现互斥锁,解决缓存击穿String key=CACHE_SHOP_KEY+id;//1.从redis查询商铺缓存String shopJson=stringRedisTemplate.opsForValue().get(key);//2.判断是否存在,isNotBlank("")也为falseif(StrUtil.isNotBlank(shopJson)){//3.存在,返回商铺对象return JSONUtil.toBean(shopJson,Shop.class);}//判断命中的是否为空值if(shopJson != null && shopJson.isEmpty()){return null;}//4.实现缓存重建String lockKey=LOCK_SHOP_KEY+id;//4.1.获取互斥锁boolean isLock=tryLock("lockKey");//4.2.判断互斥锁是否成功if(!isLock){//4.3.未成功,等待Thread.sleep(50);//递归shop=queryWithMutex(id);}else{//4.4.成功,从mysql数据库中查询shop=getById(id);//5.判断是否存在if(shop==null){//缓存空值,处理缓存穿透stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);return null;}//6.存在,向redis中缓存店铺数据stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),LOGIN_USER_TTL, TimeUnit.MINUTES);//7.释放互斥锁unlock(lockKey);}//8.返回return shop;}

2.逻辑过期:

      不存TTL,添加上逻辑过期时间,判断逻辑上有没有过期,以此来更新数据

      线程一:查询缓存,逻辑已过期,获取互斥锁,开启新线程,返回过期数据

               新线程:查询数据库并重建缓存,重置逻辑过期时间,释放锁

      线程二:查询未命中,未获得锁(已由线程一获得),返回过期数据

 private boolean tryLock(String key){//尝试获得互斥锁Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent("key","1",LOCK_SHOP_TTL,TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);//通过工具类将其转化为基本类型}private void unlock(String key){//删除锁stringRedisTemplate.delete("key");}

实现互斥锁相关的方法

//线程池,有10个线程private static final ExecutorService CACHE_REBUILD_EXECUTOR= Executors.newFixedThreadPool(10);

创建线程池

public Shop queryWithLogicalExpire(Long id) {//实现逻辑过期,解决缓存击穿(不存在缓存穿透问题)String key=CACHE_SHOP_KEY+id;String lockKey=LOCK_SHOP_KEY+id;//1.从redis查询商铺缓存String shopJson=stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if(StrUtil.isBlank(shopJson)){//3.不存在,返回nullreturn null;}//4.存在,判断是否过期//将Json反序列化成RedisDate对象RedisData redisData=JSONUtil.toBean(shopJson,RedisData.class);Shop shop=JSONUtil.toBean((JSONObject)redisData.getData(),Shop.class);//5.过期if(LocalDateTime.now().isAfter(redisData.getExpireTime())){//6.缓存重建//6.1.获取互斥锁boolean isLock=tryLock(lockKey);//6.2.获取成功if(isLock){//开启新线程CACHE_REBUILD_EXECUTOR.submit(()->{try {saveShopToRedis(id, 20L);}catch(Exception e){throw new RuntimeException(e);}finally {//释放锁unlock(lockKey);}});}//6.3.获取失败return shop;}return shop;}

逻辑删除相关方法

相关文章:

Redis:缓存击穿

缓存击穿(热点key): 部分key(被高并发访问且缓存重建业务复杂的)失效,无数请求会直接到数据库,造成巨大压力 1.互斥锁:可以保证强一致性 线程一:未命中之后,获取互斥锁,再查询数据库重建缓存,写…...

一文说清什么是数据仓库

01 数据仓库的概念 数据仓库的概念可以追溯到20世纪80年代,当时IBM的研究人员开发出了“商业数据仓库”。本质上,数据仓库试图提供一种从操作型系统到决策支持环境的数据流架构模型。 目前对数据仓库(Data Warehouse)的标准定义&a…...

【算法】哈希表相关

【ps】本篇有 5 道 leetcode OJ。 一、算法简介 哈希表是一种存储数据的容器,可以快速查找某个元素,其查找的时间复杂度为 O(1),非常合适需要频繁查找某一个元素的场景。其具体用法为: 直接使用底层为哈希表的 STL 容器。用数组…...

企微机器人:企业数字化转型的得力助手

在数字化转型的浪潮中,企业对于提高运营效率、降低人力成本的需求日益迫切。企微机器人,作为基于企业微信平台开发的一种智能工具,以其高度自动化、灵活性强、安全性高和易于使用的特点,迅速成为企业内部的得力助手。本文将深入探…...

Linux编程之socket入门教程 socket通讯原理

在Linux网络编程中,套接字Socket是进程间通信的基础,用来在网络上不同主机间进行数据的发送和接收。套接字作为一种抽象的接口,它屏蔽了底层网络协议的复杂性,使得开发者可以专注于数据的传输。以下将详细介绍Linux网络编程中的So…...

Windows上安装RabbitMQ

rabbitmq是干嘛的我就不介绍了,直接开始安装教程。 搭建成功演示图 下载安装包 https://pan.baidu.com/s/1ZlCFxh9Q00ynSU3ZCpTC9Q?pwdry51​pan.baidu.com/s/1ZlCFxh9Q00ynSU3ZCpTC9Q?pwdry51 下载完后有两个包(erlang和rabbitmq) 先安装otp_win64_24.1.7.exe…...

【C++ 高频面试题】构造函数和析构函数你了解多少呢?

文章目录 1. 什么是构造函数和析构函数2. 构造函数和析构函数可以是虚函数吗3. 构造函数有哪几种4. 深拷贝和浅拷贝的区别 1. 什么是构造函数和析构函数 🐧 构造函数: 构造函数是在创建对象时自动调用的特殊成员函数。 目的:初始化对象的成…...

linux中vim介绍以及常用命令大全

前言 在Linux系统中,Vim是一个功能强大的文本编辑器,它广泛应用于服务器管理、脚本编写和程序开发中。Vim拥有两种模式:命令模式和插入模式。了解和掌握常用的Vim命令对于提高文本编辑效率至关重要。本文将详细介绍Vim的常用命令&#xff0c…...

线性代数 第六讲 特征值和特征向量_相似对角化_实对称矩阵_重点题型总结详细解析

文章目录 1.特征值和特征向量1.1 特征值和特征向量的定义1.2 特征值和特征向量的求法1.3 特征值特征向量的主要结论 2.相似2.1 相似的定义2.2 相似的性质2.3 相似的结论 3.相似对角化4.实对称矩阵4.1 实对称矩阵的基本性质4.2 施密特正交化 5.重难点题型总结5.1 判断矩阵能否相…...

CSS“多列布局”(补充)——WEB开发系列35

多列布局是一种非常常见的布局方式,适用于内容丰富的页面,如新闻网站、杂志或博客。 一、CSS多列布局概述 CSS多列布局允许我们将内容分成多个垂直列,使页面布局更加灵活和多样化。多列布局的主要属性包括 ​​column-count​​、​​column…...

UI自动化测试痛点解决方案

前言 UI自动化测试可以快速、准确地执行大量的测试用例,减少人工测试所需的时间和劳动力。能够在短时间内完成多个测试用例的执行,提高测试的效率和速度。但是UI自动化有个最大的痛点。当前端界面发生变化时,往往页面元素定位也会改变&#…...

如何将QAD系统EDI模块无缝迁移到知行之桥?

什么是QAD系统? QAD(Quality, Applications, Development)系统,是专为制造业设计的一款ERP软件,主要包含供应链管理、生产管理、财务和客户管理等业务功能,这家公司1979年成立于美国,目前在汽车…...

Linux学习-ELK(一)

配置三台elasticsearch服务器 安装包 elasticsearch.j2 报错 #---执行rsync命令报以下错误 [rootes1 ~]# rsync -av /etc/hosts 192.168.29.172:/etc/hosts root192.168.29.172s password: bash: rsync: 未找到命令 rsync: connection unexpectedly closed (0 bytes receive…...

Selenium事件监听

引言 你一定总是渴望从WebDriver中获得更多的日志信息,以便调试你的脚本或记录更多有关测试的信息。这里为你提供了解决方案:EventFiringWebDriver 和 WebDriverEventListener。EventFiringWebDriver 是一个类,用于包装你的WebDriver以抛出事件,而WebDriverEventListener是…...

视频写作入门:9个步骤开始您的视频日志并与观众建立真实的联系

视频博客(vlogging)通过视频内容帮助你独特的声音和故事被听到,这能与你的观众建立强烈而有意义的联系,从而促进你的业务发展。使用光年AI平台,你可以将业务场景无缝接入AI能力,轻松实现私域流量的增长。 …...

使用豆包MarsCode 编写 Node.js 全栈应用开发实践

以下是「豆包MarsCode 体验官」优秀文章,作者狼叔。 欢迎更多用户使用豆包MarsCode 并分享您的产品使用心得及反馈、创意项目开发等,【有奖征集|人人都是豆包MarsCode 测评官!】活动正在火热进行中,欢迎大家投稿参加&a…...

Spring Cloud全解析:熔断之Hystrix执行流程

Hystrix执行流程 每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中执行execute()/queue做同步或异步调用判断熔断器(circuit-breaker)是否打开,如果打开则执行fallback进行降级策略,如果关闭继续执行判断线程池/队列/信号量…...

大模型算法岗,面试百问百答,7天3个offer拿到手!

导读 大模型时代很多企业都在开发自己的大模型,这直接刺激了大模型岗位的需求。本文为大家整理了大模型面试相关的知识点,希望对大家面试求职有所帮助。 今天分享大模型面试相关知识点,持续更新。 1. RAG技术体系的总体思路 数据预处理->…...

代码随想录算法day32 | 动态规划算法part05 | 完全背包,518. 零钱兑换 II, 377. 组合总和 Ⅳ,70. 爬楼梯 (进阶)

完全背包理论基础 本题力扣上没有原题,大家可以去卡码网第52题 (opens new window)去练习,题意是一样的。 完全背包 有N件物品和一个最多能背重量为W的背包。第 i 件物品的重量是 weight[i],得到的价值是 value[i] 。每件物品都有无限个&…...

【Linux 从基础到进阶】自动化备份与恢复策略

自动化备份与恢复策略 在 Linux 运维中,数据的安全性至关重要,自动化备份与恢复策略是保障系统和数据安全的核心环节。无论是系统配置文件、用户数据、数据库还是应用程序日志,备份和恢复都能为系统灾难恢复、数据丢失等突发情况提供可靠的解决方案。 本文将介绍如何在 Ce…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage)&#xff1a…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...