2.5.3 缓存穿透和缓存击穿问题讨论以及性能优化 Service:表明这是一个Spring管理的业务层组件。@Slf4j:引入日志功能,方便记录日志信息。类继承了,实现了接口,说明它是一个商铺服务的具体实现类。这段代码通过缓存机制有效解决了缓存穿透和缓存击穿问题,提高了系统的性能和稳定性。在查询商铺信息时,优先从缓存中获取,缓存未命中时再从数据库查询,并将查询结果缓存起来。对于不存在的商铺,通过缓存空对象避免了频繁的数据库查询。同时,通过互斥锁机制解决了缓存击穿问题,防止在缓存过期瞬间大量请求直接打到数据库。
2.5.2 利用逻辑过期解决缓存击穿问题 思路分析:当用户开始查询redis时,判断是否命中,如果没有命中则直接返回空数据,不查询数据库,而一旦命中后,将value取出,判断value中的过期时间是否满足,如果没有过期,则直接返回redis中的数据,如果过期,则在开启独立线程后直接返回之前的数据,独立线程去重构数据,重构完成后释放互斥锁。
2.5.1 利用互斥锁解决缓存击穿问题 核心思路:相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是 进行查询之后,如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果没有获得到,则休眠,过一会再进行尝试,直到获取到锁为止,才能进行查询如果获取到了锁的线程,再去进行查询,查询后将数据写入redis,再释放锁,返回数据,利用互斥锁就能保证只有一个线程去执行操作数据库的逻辑,防止缓存击穿。
2.3 缓存穿透问题解决思路 当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库,简单的解决方案就是哪怕这个数据在数据库中也不存在,我们也把这个数据存入到redis中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到缓存了。假设布隆过滤器判断这个数据不存在,则直接返回。
2.2.2 除了事务,Redis还有哪些机制来保证数据一致性? Redis 通过多种机制确保数据一致性,包括原子性命令、分布式锁、乐观锁、Lua 脚本、持久化机制和主从复制。这些机制共同作用,确保了在高并发环境下数据的一致性和完整性。选择合适的机制取决于具体的业务需求和应用场景。
2.2.1 原子性如何保证Redis在高并发下的数据一致性? Redis 的原子性通过单线程模型和事务机制确保了在高并发环境下数据的一致性。每个命令的执行是不可中断的,事务机制可以将多个命令打包在一起一次性执行,分布式锁和乐观锁可以进一步确保多个客户端对共享资源的互斥访问。这些机制共同作用,确保了 Redis 在高并发环境下的数据一致性。
2.2 缓存更新-数据库与缓存不一致问题 核心思路如下:修改ShopController中的业务逻辑,满足下面的需求:根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间根据id修改店铺时,先修改数据库,再删除缓存修改重点代码1:修改的queryById方法设置redis缓存时添加过期时间修改重点代码2。
2.1 Redis缓存问题 前言:什么是缓存?缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码(例如:由于其被Static修饰,所以随着类的加载而被加载到内存之中,作为本地缓存,由于其又被final修饰,所以其引用(例3:map)和对象(例3:new HashMap())之间的关系是固定的,不能改变,因此不用担心赋值(=)导致缓存失效;一句话:因为速度快,好用缓存数据存储于代码中,而代码运行在内存中,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力
1.1 Redis 简介 Redis 的原子性确保了命令的执行是不可中断的,这使得 Redis 在处理高并发请求时能够保持数据的一致性和完整性。通过使用基本命令和事务机制,可以实现复杂的业务逻辑,确保操作的原子性。
1.3 Redis 常见命令 贴心小建议:命令不要死记,学会查询就好啦Redis为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网( https://redis.io/commands )可以查看到不同的命令:当然我们也可以通过Help命令来帮助我们去查看命令。
1.7 SpringDataRedis的模版类-StringRedisTemplate 继承了类,这是MyBatis-Plus提供的一个通用服务实现类,用于简化CRUD操作,其中是数据访问层接口,ShopType是实体类。实现了接口,表示该类提供了店铺类型相关的服务功能。
1.6 SpringDataRedis的模版类-RedisTemplate 整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。这里采用了JSON序列化来代替默认的JDK序列化方式。
1.5 Redis的Java客户端-SpringDataRedis 是的子类,专门用于操作字符串类型的数据。默认使用,在处理字符串数据时更加高效和方便。是一个通用的模板类,可以操作任意类型的数据,适用于需要处理多种数据类型的情况。选择使用哪个类取决于项目的具体需求和数据类型。如果需要操作多种数据类型,则更为合适;如果只需要操作字符串数据类型,则更加高效和方便。默认使用StringRedisSerializer`,在处理字符串数据时更加高效和方便。是一个通用的模板类,可以操作任意类型的数据,适用于需要处理多种数据类型的情况。
1.4 Redis的Java客户端-Jedis 1) JedisConnectionFacotry:工厂设计模式是实际开发中非常常用的一种设计模式,我们可以使用工厂,去降低代的耦合,比如Spring中的Bean的创建,就用到了工厂设计模式。有关池化思想,并不仅仅是这里会使用,很多地方都有,比如说我们的数据库连接池,比如我们tomcat中的线程池,这些都是池化思想的体现。2)静态代码块:随着类的加载而加载,确保只能执行一次,我们在加载当前工厂类的时候,就可以执行static的操作完成对 连接池的初始化。3)最后提供返回连接池中连接的方法.
1.2 安装Redis 大多数企业都是基于Linux服务器来部署项目,而且Redis官方也没有提供Windows版本的安装包。因此课程中我们会基于Linux系统来安装Redis.方式启动,则必须修改Redis配置文件,就在我们之前解压的redis安装包下(该目录已经默认配置到环境变量,因此可以在任意目录下运行这些命令。此处选择的Linux版本为CentOS 7.,会阻塞整个会话窗口,窗口关闭或者按下。我们也可以通过配置来实现开机自启。如果没有出错,应该就安装成功了。
1.0 NoSQL 数据库简介 NoSQL(Not Only SQL),意即“不仅仅是SQL”,是指非关系型数据库系统,这类系统不依赖于传统的SQL(结构化查询语言)作为数据存储和检索的主要手段。随着大数据时代的到来,传统的关系数据库在应付Web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。