【缓存常见问题】

在使用缓存时特别是在高并发场景下会遇到很多问题,常用的问题有缓存穿透缓存击穿缓存雪崩以及缓存一致性问题。

1、缓存穿透

首先,什么是缓存穿透呢?
缓存穿透是指请求一个不存在的数据,缓存层和数据库层都没有这个数据,这种请求会穿透缓存直接到数据库进行查询。它通常发生在一些恶意用户可能故意发起不存在的请求,试图让系统陷入这种情况,以耗尽数据库连接资源或者造成性能问题。

解决方案

增加校验机制

例如:我们规定执行查询语句时,id必须是长整型而且是固定长度的格式,如果请求的id不符合则不再查询数据库。这种方案可以解决一部分的问题,还是有一定的可行性的。

缓存一个空值或者特殊值

在查询数据库的时候,发现数据不存在,此时我们依旧进行缓存,而不是直接返回。在这个时候我们可以缓存一个特殊值或者空值,避免下次请求再去访问数据库,从而避免缓存穿透。

使用布隆过滤器

后续更新。。。

2、缓存击穿

首先缓存击穿是什么呢?
缓存击穿发生在访问热点数据,大量请求访问同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据库资源,导致数据库无法使用。前提是有大量的并发。
比如某手机新品发布,当缓存失效时有大量并发到来导致同时去访问数据库。

解决方案

使用锁

单体架构下(单进程内)可以使用同步锁控制查询数据库的代码,只允许有一个线程去查询数据库,查询得到数据库存入缓存。

synchronized(obj){//查询数据库//存入缓存
}

分布式架构下(多个进程之间)可以使用分布式锁进行控制。

// 获取分布式锁对象
RLock lock = redisson.getLock("myLock");
try {// 尝试加锁,最多等待99秒,加锁后自动解锁时间为30秒boolean isLocked = lock.tryLock(99, 30, java.util.concurrent.TimeUnit.SECONDS);if (isLocked) {//查询数据库//存入缓存} else {System.out.println("获取锁失败,可能有其他线程持有锁");}
} catch (InterruptedException e) {e.printStackTrace();
} finally {// 释放锁lock.unlock();System.out.println("释放锁...");
}

此处分布式锁的实现方式有多种,大家可自行了解,我这里使用的是redisson

缓存预热
  • 分为提前预热、定时预热。
  • 提前预热就是提前写入缓存。
  • 定时预热是使用定时程序去更新缓存。
热点数据不过期

可以由后台程序提前将热点数据加入缓存缓存过期时间不过期,由后台程序做好缓存同步。

热点数据查询降级处理

对热点数据查询定义单独的接口,当缓存中不存在时走降级方法避免查询数据库。

3、缓存雪崩

什么是缓存雪崩呢?
缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。
例如对不同的几类信息设置相同的过期时间,在大量请求第一次查询这些信息时,会写入缓存当中,当过期时间一到,就会有大量的信息访问数据库,从而引发雪崩问题。

解决方案

对同一类型信息的key设置不同的过期时间

通常对一类信息的key设置的过期时间是相同的,这里可以在原有固定时间的基础上加上一个随机时间使它们的过期时间都不相同
例如:

@Beanpublic RedisCacheManager cacheManagerOneDay(RedisConnectionFactory connectionFactory) {int randomNum = new Random().nextInt(9999);RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()//过期时间为基础时间加随机数.entryTtl(Duration.ofSeconds(48 * 60 * 60L + randomNum)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(JACKSON_SERIALIZER));return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).transactionAware().build();}
使用锁进行控制

思路同缓存击穿。

缓存定时预热

不用等到请求到来再去查询数据库存入缓存,可以提前将数据存入缓存。使用缓存预热机制通常有专门的后台程序去将数据库的数据同步到缓存。

4、缓存数据不一致问题

什么数缓存数据不一致呢?
缓存不一致问题是指当发生数据变更后该数据在数据库和缓存中是不一致的,此时查询缓存得到的并不是与数据库一致的数据。
经典案例:双写不一致

解决方案

使用分布式锁
延迟双删

延迟多长时间呢?
主数据向从数据库同步的时间间隔,如果延迟时间设置不合理也会导致数据不一致。

使用canal+mq的方式

延迟双删的目的也是为了保证最终一致性,即允许缓存短暂不一致,最终保证一致性。
保证最终一致性的方案有很多,比如:通过MQ、Canal、定时任务都可以实现。
Canal是一个数据同步工具,读取MySQL的binlog日志拿到更新的数据,再通过MQ发送给异步同步程序,最终由异步同步程序写到redis。此方案适用于对数据实时性有一定要求的场景。
通过Canal加MQ异步任务方式流程如下:

whiteboard_exported_image.png

流程如下:
线程1写数据库
canal读取binlog日志,将数据变化日志写入mq
同步程序监听mq接收到数据变化的消息
同步程序解析消息内容写入redis,写入redis成功正常消费完成,消息从mq删除。

定时任务方式流程如下:
专门启动一个数据同步任务定时读取数据同步到redis,此方式适用于对数据实时性要求不强更新不频繁的数据。2.png

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

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

相关文章

虚拟天空解决方案,创造出令人惊叹的换天效果

在汽车视频领域,如何打破传统拍摄限制,呈现出更具创意和想象力的画面,成为众多企业和创作者追求的目标。美摄科技作为业界领先的视频技术提供商,凭借其强大的AI技术和三维渲染引擎,推出了全新的虚拟天空解决方案&#…

集成电路测试学习

集成电路(Integrated Circuit,IC)整个设计流程包括:电路设计、晶圆制造、晶圆测试、IC封装、封装后测试。 IC测试目的:一、确认芯片是否满足产品手册上定义的规范;二、通过测试测量,确认芯片可以…

李国武:QFD是如何将顾客需求转换为产品技术要求的?

如何将顾客的多样化需求精准地转化为产品的技术要求,成为企业赢得市场、提升竞争力的关键。质量功能展开(Quality Function Deployment,简称QFD)作为一种先进的质量管理工具,正是实现这一转换的有效桥梁。具体如天行健…

vim相关指令

vim的各种模式及其转换关系图 vim 默认处于命令模式!!! 模式之间转换的指令 除【命令模式】之外,其它模式要切换到【命令模式】,只需要无脑 ESC 即可!!! [ 命令模式 ] 切换至 [ 插…

unity动画的关键帧添加event-同步语音

在iclone中做的语音嘴型动画,因是用下图自带的方式语音生成的动画,而不是用plugin(面捕live会连同语音一起导出),所以导出来到Unity中,之后口型、动作、表情等没有声音。 我需要把原有的语音也重新在unity中加载上,原来…

解决WPS右键菜单冗余选项,去除WPS右键菜单选项

问题描述 安装WPS后,右键菜单会多出许多无用的选项,如何去除? 解决方法 按下WindowsS打开搜索栏,搜索配置工具打开 勾选所有的关闭和隐藏选项

汽车视频智能剪辑解决方案,满足用户对高品质汽车视频的追求

随着汽车智能化和互联网技术的快速发展,车载视频已经成为现代驾驶生活不可或缺的一部分。然而面对海量的行车视频,如何高效地剪辑、整理并分享这些精彩瞬间,一直是车主和汽车内容创作者们所面临的难题。美摄科技,作为领先的视频智…

Postgres数据库中的死锁是如何产生的,如何避免和解决?

文章目录 死锁的产生原因如何避免死锁如何解决死锁示例代码查询死锁信息终止事务 在Postgres数据库中,死锁是一种特殊的情况,其中两个或多个事务相互等待对方释放资源,从而导致它们都无法继续执行。这种情况通常发生在多个事务尝试以不同的顺…

SQL255 给出employees表中排名为奇数行的first_name

题目来源: 给出employees表中排名为奇数行的first_name_牛客题霸_牛客网 描述 对于employees表中,输出first_name排名(按first_name升序排序)为奇数的first_name CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, firs…

高德地图API-鼠标点击地图获取经纬度坐标(关键操作)

效果图&#xff1a; 有了经纬度坐标&#xff0c;就可以得到城市的&#xff1a;adcode区域编码 html版本 <!doctype html> <html> <head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&g…

Unity类银河恶魔城学习记录13-1 p142 Save system源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

数据结构学习记录

数据结构 数组 & 链表 相连性 | 指向性 数组可以迅速定位到数组中某一个节点的位置 链表则需要通过前一个元素指向下一个元素&#xff0c;需要前后依赖顺序查找&#xff0c;效率较低 实现链表 // head > node1 > node2 > ... > nullclass Node {constructo…

基于springboot+vue+Mysql的社区维修平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

软件产品许可证书 Licence 全流程研发(使用非对称加密技术,既安全又简单)

本篇博客对应的代码地址&#xff1a; Gitee 仓库地址&#xff1a;https://gitee.com/biandanLoveyou/licence 源代码百度网盘链接: https://pan.baidu.com/s/1_ZhdcENcrk2ZuL11hWDLTQ?pwdbmxi 提取码: bmxi 1、背景介绍 公司是做软件 SAAS 服务的&#xff0c;一般来说软件部…

RabbitMQ项目实战(一)

文章目录 RabbitMQ项目实战选择客户端基础实战 前情提要&#xff1a;我们了解了消息队列&#xff0c;RabbitMQ的入门&#xff0c;交换机&#xff0c;以及核心特性等知识&#xff0c;现在终于来到了激动人心的项目实战环节&#xff01;本小节主要介绍通过Spring Boot RabbitMQ S…

2021年全国大学生电子设计竞赛D题——基于互联网的摄像测量系统(三)

13 测试方案和测量结果 测量一个边长为1米的正方形&#xff0c;取三个顶点分别作为O、A、B点。 在O点上方&#xff0c;用细线悬挂激光笔&#xff0c;激光笔常亮向下指示&#xff0c;静止时激光笔的光点和O点重合。 将两个D8M摄像头子卡插到DE10-Nano开发板上&#xff0c;放…

MySQL Linux环境安装部署

目录 1、mysql安装包下载 2、安装mysql服务 3、启动mysql服务 4、登录mysql服务 1、mysql安装包下载 1、查看centos的版本 cat /etc/redhat-release 2、进入官网地址下载对应系统版本的安装包 地址&#xff1a;MySQL :: Download MySQL Yum Repository 2、安装mysql服务 …

恒峰智慧科技-森林消防便捷泵:轻松应对火灾危机!

在广袤无垠的森林中&#xff0c;绿色是生命的象征&#xff0c;是自然的馈赠。然而&#xff0c;当火魔无情地吞噬这片生命的绿洲时&#xff0c;我们需要一种快速、高效、可靠的消防工具来守护这片绿色。此时&#xff0c;森林消防便捷泵应运而生&#xff0c;成为了守护森林安全的…

Oracle数据库 :查询表结构脚本

查询脚本 &#xff1a; SELECT CASE WHEN a.column_id1 THEN a.TABLE_NAME ELSE END AS 表名, a.column_id AS 序号, a.column_name as 列名, REPLACE(comments, CHR(10), ) as 列说明, a.data_type || ( || a.data_length || ) as 数据类型, a.DATA_LENGTH AS 长度, a.DATA_…

idea中停止运行Vue

在里面敲入Ctrlc 输入y确定即可。