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

关于Redis(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));

热点数据缓存:

为了把一些经常访问的数据,放入缓存中以减少对数据库的访问频率。从而减少数据库的压力,提高程序的性能。【内存中存储】成为缓存;

缓存适合存放的数据:
  1. 查询频率高且修改频率低

  2. 数据安全性低

作为缓存的组件:
  1. redis组件

  2. memory组件

  3. ehcache组件

Redis实现缓存功能
涉及的内容:

spring缓存组件 Redis数据库 AOP面向切面编程

实现:
Spirng缓存组件
//开启缓存注解
@EnableCaching
public class CalassNameApplication {public static void main (String[] arge) {SpringApplication.run(CalssNameApplication.class,args);}
}
添加注解
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)) //缓存过期10分钟 ---- 业务需求。.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//设置key的序列化方式.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //设置value的序列化.disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;
}
实现缓存功能
//所在的类和注入
@Service
public class ClazzServiceImpl implements ClazzService {
​@Autowiredprivate ClazzDao clazzDao;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
查询
  1. 查询缓存中是否存在名称为cacheNames::key的值

  2. 如果存在则方法不会执行

  3. 如果不存在则执行方法体并把方法的返回结果放入缓存cacheNames::key

//Cacheable:表示查询时使用的注解。
//cacheNames:缓存的名称
//key:缓存的唯一表示值
@Cacheable(cacheNames ={ "clazz"}, key = "#id")
@Override
public Clazz getById(Integer id) {//查询数据库Clazz clazz = clazzDao.selectById(id);return clazz;
}
修改
  1. 先执行方法体

  2. 把方法的返回结果放入缓存中

//CachePut:表示修改时使用的注解.
//cacheNames:缓存的名称
//key:缓存的唯一表示值
@CachePut(cacheNames = "clazz", key = "#clazz.cid")
public Clazz update(Clazz clazz) {//修改数据库int i = clazzDao.updateById(clazz);return clazz;
}
删除
  1. 先执行方法体

  2. 把缓存中名称为cacheNames::key的值删除

//CacheEvict:表示删除时使用的注解
//cacheNames:缓存的名称
//key:缓存的唯一表示值
@CacheEvict(cacheNames = "clazz", key = "#cid")
@Override
public int delete(Integer cid) {int i = clazzDao.deleteById(cid);return i;
}
原理:
@Service
public class ClazzServiceImpl implements ClazzService {
​@Autowiredprivate ClazzDao clazzDao;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic Clazz getById(Integer id) {//1.查询redis缓存是否命中ValueOperations<String, Object> forValue = redisTemplate.opsForValue();Object o = forValue.get("clazz::" + id);//表示缓存命中if(o!=null){return (Clazz) o;}//查询数据库Clazz clazz = clazzDao.selectById(id);if(clazz!=null){forValue.set("clazz::" + id,clazz);}return clazz;}
​@Overridepublic Clazz save(Clazz clazz) {int insert = clazzDao.insert(clazz);return clazz;}
​@Overridepublic Clazz update(Clazz clazz) {//修改数据库int i = clazzDao.updateById(clazz);if(i>0){//修改缓存redisTemplate.opsForValue().set("clazz::"+clazz.getCid(),clazz);}return clazz;}
​@Overridepublic int delete(Integer cid) {int i = clazzDao.deleteById(cid);if(i>0){//删除缓存redisTemplate.delete("clazz::"+cid);}return i;}
}

分布式锁:

自理解:

分布式:一个网站部署多台服务器

锁:保证线程安全(将并行改为串行)只允许同时只有一个可以访问;

分布式锁:通过共享的锁保证每台服务器都能共享到同一个实时数据(进行操作);

涉及内容:

syn和lock锁 nginx代理群 Redis数据库 看门狗redisson

使用工具:

Jmeter压测工具 nginx代理

Jmeter:

模拟高并发工具

使用:
分布式锁实现:
@Service
public class StockService {
​@Autowiredprivate StockDao stockDao;@Autowiredprivate RedissonClient redisson;
​//public String decrement(Integer productid) {RLock lock = redisson.getLock("product::" + productid);lock.lock();try {//根据id查询商品的库存: 提前预热到redis缓存中int num = stockDao.findById(productid);if (num > 0) {//修改库存---incr---定时器[redis  数据库同步]stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}finally {lock.unlock();}}
}
原理:
  1. 加入syn和lock锁;

    syn和lock虽然解决了并发问题,但是项目部署时可能要部署集群模式。

     public String decrement(Integer productid) {//根据id查询商品的库存int num = stockDao.findById(productid);synchronized (this) {
    ​if (num > 0) {//修改库存stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}}

  1. nginx集群部署并使用redis解决分布式锁文件;

    打开并使用nginx代理集群exe文件;

    nginx(详细操作见linux笔记内):
    代理集群使用
    配置文件:nginx/conf/nginx.conf
    @Service
    public class StockService {
    ​@Autowiredprivate StockDao stockDao;@Autowiredprivate StringRedisTemplate redisTemplate;//public String decrement(Integer productid) {ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();//1.获取共享锁资源Boolean flag = opsForValue.setIfAbsent("product::" + productid, "1111", 30, TimeUnit.SECONDS);//表示获取锁成功if(flag) {try {//根据id查询商品的库存int num = stockDao.findById(productid);if (num > 0) {//修改库存stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}finally {//释放锁资源redisTemplate.delete("product::"+productid);}}else{//休眠100毫秒 在继续抢锁try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}return decrement(productid);}}
    }

  1. redis超时问题[业务代码执行时间超过了上锁时间]

    使用第三方redisson插件
    <!--引入redisson依赖,看门狗-->
    <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.24.3</version>
    </dependency>
    //配置文件
    @Configuration
    public class RedissonConfig {
    ​@Beanpublic RedissonClient redisson(){Config config = new Config();
    //        //连接的为redis集群
    //        config.useClusterServers()
    //                // use "rediss://" for SSL connection
    //                .addNodeAddress("redis://127.0.0.1:7181","","","")
    //        ;//连接单机config.useSingleServer().setAddress("redis://172.16.7.18:6379");RedissonClient redisson = Redisson.create(config);return redisson;}
    }
    代码实现:
    @Service
    public class StockService {
    ​@Autowiredprivate StockDao stockDao;@Autowiredprivate RedissonClient redisson;
    ​//public String decrement(Integer productid) {RLock lock = redisson.getLock("product::" + productid);lock.lock();try {//根据id查询商品的库存: 提前预热到redis缓存中int num = stockDao.findById(productid);if (num > 0) {//修改库存---incr---定时器[redis  数据库同步]stockDao.update(productid);System.out.println("商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个");return "商品编号为:" + productid + "的商品库存剩余:" + (num - 1) + "个";} else {System.out.println("商品编号为:" + productid + "的商品库存不足。");return "商品编号为:" + productid + "的商品库存不足。";}}finally {lock.unlock();}}
    }

问题集:

使用StringRedisTemplate调用get方法获取map数据,使用String接出现

org.springframework.data.redis.RedisSystemException:Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: WRONGTYPE Operation against a key holding the wrong kind of value

DefaultSerializer需要一个可序列化的有效负载,但接收到一个类型的对象

java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.day51.entity.MyEntity]

缓存安全:

什么是缓存穿透以及如何解决?

缓存穿透: 查询的数据在数据库中不存在缓存中也不存在,这时有人恶意访问这种数据,请求到达数据库。

解决方案 :

第一步:在controller层校验数据。对一些不合法的数据过滤掉.

第二步: 使用bloom布隆过滤器。

第三步: 存放一个空对象,并且设置过期时间不能超过5分钟。

什么是缓存击穿以及如何解决?

缓存击穿: 数据库中存在,但是缓存中该数据过期了。这是有大量的请求访问该过期的数据。压力顶到数据库。

解决方案: [1]使用互斥锁 [2]设置永不过期。

什么是缓存雪崩以及如何解决?

缓存雪崩: 当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

解决方案: [1] 设置散列的过期时间。 [2]预热数据 [3]搭建redis集群

相关文章:

关于Redis(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));

热点数据缓存: 为了把一些经常访问的数据&#xff0c;放入缓存中以减少对数据库的访问频率。从而减少数据库的压力&#xff0c;提高程序的性能。【内存中存储】成为缓存; 缓存适合存放的数据: 查询频率高且修改频率低 数据安全性低 作为缓存的组件: redis组件 memory组件 e…...

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十七章 字符设备和杂项设备总结回顾

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...

C#初级——枚举

枚举 枚举是一组命名整型常量。 enum 枚举名字 { 常量1, 常量2, …… 常量n }; 枚举的常量是由 , 分隔的列表。并且&#xff0c;在这个整型常量列表中&#xff0c;通常默认第一位枚举符号的值为0&#xff0c;此后的枚举符号的值都比前一位大1。 在将枚举赋值给 int 类型的…...

Linux 动静态库

一、动静态库 1、库的理解 库其实是给我们提供方法的实现&#xff0c;如上面的对于printf函数的实现就是在库中实现的&#xff0c;而这个库也就是c标准库&#xff0c;本质也是文件&#xff0c;也有对应的路径 2、区别 静态库是指编译链接时&#xff0c;把库文件的代码全部加入…...

微信小游戏之 三消(一)

首先设定一下 单个 方块 cell 类&#xff1a; 类定义和属性 init 方法 用于初始化方块&#xff0c;接收游戏实例、数据、宽度、道具类型和位置。 onWarning 方法 设置警告精灵的帧&#xff0c;并播放闪烁动作&#xff0c;用于显示方块的警告状态。 grow 方法 根据传入的方向…...

软件测试---Linux

Linux命令使用&#xff1a;为了将来工作中与服务器设备进行交互而准备的技能&#xff08;远程连接/命令的使用&#xff09;数据库的使用&#xff1a;MySQL&#xff0c;除了查询动作需要重点掌握以外&#xff0c;其他操作了解即可什么是虚拟机 通过虚拟化技术&#xff0c;在电脑…...

数据库之数据表基本操作

目录 一、创建数据表 1.创建表的语法形式 2.使用SQL语句设置约束条件 1.设置主键约束 2.设置自增约束 3.设置非空约束 4.设置唯一性约束 5.设置无符号约束 6.设置默认约束 7.设置外键约束 8.设置表的存储引擎 二、查看表结构 1.查看表基本结构 2.查看建表语句 三…...

利用OSMnx求路网最短路径并可视化(二)

书接上回&#xff0c;为了增加多路径的可视化效果和坐标匹配最近点来实现最短路可视化&#xff0c;我们使用图形化工具matplotlib结合OSMnx的绘图功能来展示整个路网图&#xff0c;并特别高亮显示计算出的最短路径。 多起终点最短路路径并计算距离和时间 完整代码#运行环境 P…...

双向门控循环神经网络(BiGRU)及其Python和MATLAB实现

BiGRU是一种常用的深度学习模型&#xff0c;用于处理序列数据的建模和预测。它是基于GRU&#xff08;Gated Recurrent Unit&#xff09;模型的改进版本&#xff0c;通过引入更多的隐藏层和增加网络的宽度&#xff0c;能够更好地捕捉复杂的序列数据中的模式。 背景&#xff1a;…...

【BUG】已解决:ERROR: Failed building wheel for jupyter-nbextensions-configurator

ERROR: Failed building wheel for jupyter-nbextensions-configurator 目录 ERROR: Failed building wheel for jupyter-nbextensions-configurator 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我…...

Unity UGUI 之 自动布局组件

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本&#xff0c;请注意分别 1.什么是自动布局组件…...

网络基础之(11)优秀学习资料

网络基础之(11)优秀学习资料 Author&#xff1a;Once Day Date: 2024年7月27日 漫漫长路&#xff0c;有人对你笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的博客-CSDN博客。 参考文档&#xff1a; 网络工程初学者的学习方法及成长之路&#xff08;红…...

QT自定义无边框窗口(可移动控制和窗口大小调整)

QT是一个功能强大的跨平台开发框架&#xff0c;它提供了丰富的界面设计工具和组件。在界面开发中&#xff0c;QT窗口自带的标题栏无法满足我们的需求。我们就需要自定义无边框窗口&#xff0c;包括自定义标题栏和窗口大小调整功能。本文将介绍如何在QT中实现这些功能。 一、简…...

Typora 【最新1.8.6】版本安装下载教程 (轻量级 Markdown 编辑器),图文步骤详解,免费领取(软件可激活使用)

文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 Typora 是一款专为 Markdown 爱好者设计的文本编辑器&#xff0c;它结合了简洁的界面设计与强大的 Markdown 渲染能力&#xff0c;为用户提供了一个流畅、高效的写作环境。以下是对 Typora 更详细的介绍&#xff1a; 核心特…...

RxJava 面试题及其答案

以下是一个全面的 RxJava 面试题及其答案&#xff0c;涵盖了 RxJava 的各个方面&#xff0c;包括基本概念、操作符、线程管理、错误处理、背压处理等&#xff1a; 基本概念 1. RxJava 的基本概念和原理是什么&#xff1f; 答案&#xff1a; RxJava 是一个用于响应式编程的库…...

【Rust】所有权OwnerShip

什么是所有权 rust使用由编译器检查的一些规则构成的所有权系统来管理内存。且这不会影响程序的运行效率。 所有权规则 rust中每一个每一个值都有一个owner。在同一时刻&#xff0c;只能有一个owner。当这个owner超过范围&#xff0c;则该值会被丢弃。 String类型 为什么需…...

qt总结--翻金币案例

完成了一个小项目的在qt5.15.2环境下的运行,并使用NSIS editNSIS打包完成.有待改进之处:增加计时功能,随机且能通关功能,过关后选择下一关功能.打包后仅仅有安装包有图标 安装后应用图标并未改变 在qt .pro中有待改进对qt的基本操作和帮助文档有了基本的认识.对C制作小游戏有了…...

最清楚的 BIO、NIO、AIO 详解!

一、什么是 I/O&#xff1f; I/O 描述了计算机系统与外部设备&#xff08;磁盘&#xff09;之间通信的过程。 为了保证操作系统的稳定性和安全性&#xff0c;一个进程的地址空间划分为 用户空间&#xff08;User space&#xff09; 和 内核空间&#xff08;Kernel space &…...

八股文学习第二天| HTTP请求报文和响应报文是怎样的,有哪些常见的字段?,HTTP有哪些请求方式?,GET请求和POST请求的区别?

1、HTTP请求报文和响应报文是怎样的&#xff0c;有哪些常见的字段&#xff1f; 答&#xff1a; HTTP报文分为请求报文和响应报文。 &#xff08;1&#xff09; 请求报文 请求报文主要由请求行、请求头、空行、请求体构成。 请求行包括如下字段&#xff1a; 方法&#xff08…...

C++初阶学习第四弹——类与对象(中)

目录 一. 类的默认成员函数 二.六种默认成员函数 1、构造函数 1.1 构造函数的作用 1.2 特性 1.3 默认构造函数 2、析构函数 2.1 析构函数的作用 2.2 析构函数的用法 3、拷贝构造函数 3.1 拷贝构造函数的作用 3.2 特征 3.3 默认拷贝构造函数 三.总结 类与对象&…...

XUnity.AutoTranslator完整指南:让外语游戏瞬间变中文的免费神器

XUnity.AutoTranslator完整指南&#xff1a;让外语游戏瞬间变中文的免费神器 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为语言障碍而无法畅玩海外Unity游戏吗&#xff1f;XUnity.AutoTranslator…...

LlamaGen:自回归模型在图像生成领域挑战扩散模型

1. 项目概述&#xff1a;当Llama遇见图像生成最近在图像生成领域&#xff0c;一个名为LlamaGen的项目引起了我的注意。它提出了一个非常大胆且反直觉的观点&#xff1a;纯自回归模型&#xff08;AR&#xff09;在图像生成任务上&#xff0c;可以超越当前如日中天的扩散模型&…...

构建支持多模型切换的智能内容审核与打标系统

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 构建支持多模型切换的智能内容审核与打标系统 在用户生成内容平台中&#xff0c;视频、图文等内容的审核与分类打标是核心运营环节…...

杰理之做1T1应用失真较大问题修改【篇】

可以将低延时编码LIVE_AUDIO_CODING_JLA_LL修改为LIVE_AUDIO_CODING_JLA...

开发AI应用时借助Taotoken模型广场快速进行模型选型与测试

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 开发AI应用时借助Taotoken模型广场快速进行模型选型与测试 在开发基于大语言模型的应用或功能时&#xff0c;一个常见的挑战是如何…...

PyTorch深度学习资源大全:如何快速找到最佳教程和项目库的终极指南

PyTorch深度学习资源大全&#xff1a;如何快速找到最佳教程和项目库的终极指南 【免费下载链接】the-incredible-pytorch The Incredible PyTorch: a curated list of tutorials, papers, projects, communities and more relating to PyTorch. 项目地址: https://gitcode.c…...

私域团队如何用企业微信 API 提升客户维护效率?

一、 场景描述&#xff1a;为什么你的团队每天都在“瞎忙”&#xff1f; 很多私域团队看似忙碌&#xff0c;实则效率低下。典型的现象包括&#xff1a; • 重复回答&#xff1a;每天 70% 的时间在复制粘贴相同的话术&#xff08;如&#xff1a;发货时间、优惠券怎么领&#xff…...

芯片高加速温湿度测试HAST:从步骤到报告讲解

其可靠性和稳定性成为消费者和制造商关注的焦点。高加速温湿度测试&#xff08;Highly Accelerated Stress Test, HAST&#xff09;作为一种有效的可靠性测试方法&#xff0c;近年来在行业内得到了广泛的应用。本文将从HAST测试的步骤、实际案例以及如何生成详细的测试报告等方…...

Ubuntu服务器性能检测工具NetData安装

1. NetData安装 打开Ubuntu终端并输入以下指令&#xff1a; $ bash <(curl -Ss https://my-netdata.io/kickstart-static64.sh)中途会提示安装文件将为占用磁盘空间&#xff0c;是否继续&#xff08;Y/N&#xff09;&#xff0c;输入Y即可&#xff0c;安装完成后的截图如下…...

2026快消日化CRM选型指南,这几点一定注意

针对洗护日化行业SKU繁杂、全渠道&#xff08;KA/CS/母婴&#xff09;管理难的技术痛点&#xff0c;企业在CRM选型时必须关注SFA执行、DMS协同及ERP深度集成的能力。我们在日化赛道&#xff0c;通过勤策SFAAI Agent方案&#xff0c;帮客户把陈列识别准确率提升至98%&#xff0c…...