关于Redis(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));
热点数据缓存:
为了把一些经常访问的数据,放入缓存中以减少对数据库的访问频率。从而减少数据库的压力,提高程序的性能。【内存中存储】成为缓存;
![]()
缓存适合存放的数据:
查询频率高且修改频率低
数据安全性低
作为缓存的组件:
redis组件
memory组件
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;查询
查询缓存中是否存在名称为cacheNames::key的值
如果存在则方法不会执行
如果不存在则执行方法体并把方法的返回结果放入缓存cacheNames::key
//Cacheable:表示查询时使用的注解。 //cacheNames:缓存的名称 //key:缓存的唯一表示值 @Cacheable(cacheNames ={ "clazz"}, key = "#id") @Override public Clazz getById(Integer id) {//查询数据库Clazz clazz = clazzDao.selectById(id);return clazz; }修改
先执行方法体
把方法的返回结果放入缓存中
//CachePut:表示修改时使用的注解. //cacheNames:缓存的名称 //key:缓存的唯一表示值 @CachePut(cacheNames = "clazz", key = "#clazz.cid") public Clazz update(Clazz clazz) {//修改数据库int i = clazzDao.updateById(clazz);return clazz; }删除
先执行方法体
把缓存中名称为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();}} }原理:
加入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 + "的商品库存不足。";}}}
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);}} }
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(热点数据缓存,分布式锁,缓存安全(穿透,击穿,雪崩));
热点数据缓存: 为了把一些经常访问的数据,放入缓存中以减少对数据库的访问频率。从而减少数据库的压力,提高程序的性能。【内存中存储】成为缓存; 缓存适合存放的数据: 查询频率高且修改频率低 数据安全性低 作为缓存的组件: redis组件 memory组件 e…...
【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十七章 字符设备和杂项设备总结回顾
i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...
C#初级——枚举
枚举 枚举是一组命名整型常量。 enum 枚举名字 { 常量1, 常量2, …… 常量n }; 枚举的常量是由 , 分隔的列表。并且,在这个整型常量列表中,通常默认第一位枚举符号的值为0,此后的枚举符号的值都比前一位大1。 在将枚举赋值给 int 类型的…...
Linux 动静态库
一、动静态库 1、库的理解 库其实是给我们提供方法的实现,如上面的对于printf函数的实现就是在库中实现的,而这个库也就是c标准库,本质也是文件,也有对应的路径 2、区别 静态库是指编译链接时,把库文件的代码全部加入…...
微信小游戏之 三消(一)
首先设定一下 单个 方块 cell 类: 类定义和属性 init 方法 用于初始化方块,接收游戏实例、数据、宽度、道具类型和位置。 onWarning 方法 设置警告精灵的帧,并播放闪烁动作,用于显示方块的警告状态。 grow 方法 根据传入的方向…...
软件测试---Linux
Linux命令使用:为了将来工作中与服务器设备进行交互而准备的技能(远程连接/命令的使用)数据库的使用:MySQL,除了查询动作需要重点掌握以外,其他操作了解即可什么是虚拟机 通过虚拟化技术,在电脑…...
数据库之数据表基本操作
目录 一、创建数据表 1.创建表的语法形式 2.使用SQL语句设置约束条件 1.设置主键约束 2.设置自增约束 3.设置非空约束 4.设置唯一性约束 5.设置无符号约束 6.设置默认约束 7.设置外键约束 8.设置表的存储引擎 二、查看表结构 1.查看表基本结构 2.查看建表语句 三…...
利用OSMnx求路网最短路径并可视化(二)
书接上回,为了增加多路径的可视化效果和坐标匹配最近点来实现最短路可视化,我们使用图形化工具matplotlib结合OSMnx的绘图功能来展示整个路网图,并特别高亮显示计算出的最短路径。 多起终点最短路路径并计算距离和时间 完整代码#运行环境 P…...
双向门控循环神经网络(BiGRU)及其Python和MATLAB实现
BiGRU是一种常用的深度学习模型,用于处理序列数据的建模和预测。它是基于GRU(Gated Recurrent Unit)模型的改进版本,通过引入更多的隐藏层和增加网络的宽度,能够更好地捕捉复杂的序列数据中的模式。 背景:…...
【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 欢迎来到我的主页,我…...
Unity UGUI 之 自动布局组件
本文仅作学习笔记与交流,不作任何商业用途 本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本,请注意分别 1.什么是自动布局组件…...
网络基础之(11)优秀学习资料
网络基础之(11)优秀学习资料 Author:Once Day Date: 2024年7月27日 漫漫长路,有人对你笑过嘛… 全系列文档可参考专栏:通信网络技术_Once-Day的博客-CSDN博客。 参考文档: 网络工程初学者的学习方法及成长之路(红…...
QT自定义无边框窗口(可移动控制和窗口大小调整)
QT是一个功能强大的跨平台开发框架,它提供了丰富的界面设计工具和组件。在界面开发中,QT窗口自带的标题栏无法满足我们的需求。我们就需要自定义无边框窗口,包括自定义标题栏和窗口大小调整功能。本文将介绍如何在QT中实现这些功能。 一、简…...
Typora 【最新1.8.6】版本安装下载教程 (轻量级 Markdown 编辑器),图文步骤详解,免费领取(软件可激活使用)
文章目录 软件介绍软件下载安装步骤激活步骤 软件介绍 Typora 是一款专为 Markdown 爱好者设计的文本编辑器,它结合了简洁的界面设计与强大的 Markdown 渲染能力,为用户提供了一个流畅、高效的写作环境。以下是对 Typora 更详细的介绍: 核心特…...
RxJava 面试题及其答案
以下是一个全面的 RxJava 面试题及其答案,涵盖了 RxJava 的各个方面,包括基本概念、操作符、线程管理、错误处理、背压处理等: 基本概念 1. RxJava 的基本概念和原理是什么? 答案: RxJava 是一个用于响应式编程的库…...
【Rust】所有权OwnerShip
什么是所有权 rust使用由编译器检查的一些规则构成的所有权系统来管理内存。且这不会影响程序的运行效率。 所有权规则 rust中每一个每一个值都有一个owner。在同一时刻,只能有一个owner。当这个owner超过范围,则该值会被丢弃。 String类型 为什么需…...
qt总结--翻金币案例
完成了一个小项目的在qt5.15.2环境下的运行,并使用NSIS editNSIS打包完成.有待改进之处:增加计时功能,随机且能通关功能,过关后选择下一关功能.打包后仅仅有安装包有图标 安装后应用图标并未改变 在qt .pro中有待改进对qt的基本操作和帮助文档有了基本的认识.对C制作小游戏有了…...
最清楚的 BIO、NIO、AIO 详解!
一、什么是 I/O? I/O 描述了计算机系统与外部设备(磁盘)之间通信的过程。 为了保证操作系统的稳定性和安全性,一个进程的地址空间划分为 用户空间(User space) 和 内核空间(Kernel space &…...
八股文学习第二天| HTTP请求报文和响应报文是怎样的,有哪些常见的字段?,HTTP有哪些请求方式?,GET请求和POST请求的区别?
1、HTTP请求报文和响应报文是怎样的,有哪些常见的字段? 答: HTTP报文分为请求报文和响应报文。 (1) 请求报文 请求报文主要由请求行、请求头、空行、请求体构成。 请求行包括如下字段: 方法(…...
C++初阶学习第四弹——类与对象(中)
目录 一. 类的默认成员函数 二.六种默认成员函数 1、构造函数 1.1 构造函数的作用 1.2 特性 1.3 默认构造函数 2、析构函数 2.1 析构函数的作用 2.2 析构函数的用法 3、拷贝构造函数 3.1 拷贝构造函数的作用 3.2 特征 3.3 默认拷贝构造函数 三.总结 类与对象&…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...
