关于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 默认拷贝构造函数 三.总结 类与对象&…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
