谷粒商城-缓存-缓存使用

谷粒商城-缓存-缓存使用,第1张

目录

缓存-缓存使用-本地缓存与分布式缓存

缓存-缓存使用-整合Redis测试

缓存-缓存使用-改造三级分类业务

缓存-缓存使用-压力测试出的内存泄漏及解决

缓存-缓存使用-缓存击穿、穿透、雪崩

缓存-缓存使用-加锁解决缓存击穿的问题

缓存-缓存使用-本地锁在分布式下的问题


缓存-缓存使用-本地缓存与分布式缓存

使用缓存的好处:提升系统的性能

什么样的数据适合存储到缓存中?

①及时性、数据一致性要求不高的数据,例如物流信息、商品类目信息

②访问量大更新频率不高的数据(读多、写少)

读模式下的使用缓存的流程如下图所示: 

本地缓存使用的伪代码如下图所示:

本地缓存最简单的方式就是编写一个Map 

使用本地缓存存在的问题: 

问题1:

加入请求负载均衡交由服务1处理,服务1将数据从数据库中查出存放到缓存中,但不能保证每次负载均衡到同一个服务,负载到其它服务时,需要再次从数据库中查出数据存放到缓存中。

问题2:

加入需要修改类目,修改请求被负载均衡到服务1,服务1修改了类目并且修改了缓存中的数据,但是负载均衡到其它服务时,其它服务的缓存数据并未被修改,会导致数据不一致的。

解决方案:

使用集中的缓存中间件,解决了上述问题的同时还解决了缓存不足的问题,可以将缓存中间件集群化

分布式缓存

缓存-缓存使用-整合Redis测试

Redis的整合步骤:

①导入data-redis-starter

        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        

ctrl+n 搜索 RedisAutoConfiguration

SpringBoot自动配置好了redisTemplate、StringRedisTemplate用于 *** 作,RedisstringRedisTemplate是用于存放类型的数据

关于Redis配置的属性都放在RedisProperties中

②简单配置Redis的host等信息 

Redis配置,需要配置redis的主机地址和端口号,不配置端口号默认为6379,还可以配置密码

③使用SpringBoot自动配置好的StringRedisTemplate来 *** 作redis

 

缓存-缓存使用-改造三级分类业务

①将原先的三级分类查询的方法中的@Override去掉,换取新的方法名作为业务处理的方法

② 在原先的实现三级分类查询的方法中编写缓存的使用

要指定value的类型为String,因为String实现了序列化接口,否则存储到redis中的数据会乱码 

我们将java对象转化为跨语言、跨平台兼容的json存入到缓存中即为序列化

我们将json数据转化为可用的java对象,即为反序列化

缓存-缓存使用-压力测试出的内存泄漏及解决

压测三级分类目录

由于我使用的data-redis-starter是2.3.7版本的,SpringBoot已经针对lettuce进行了优化未出现堆外内存溢出的现象

这里总结一下如果使用data-redis-starter出现堆外内存溢出的解决方案

出现问题:使用data-redis-starter出现堆外内存溢出即OutOfDireMemoryError

出现问题的原因:lettuce使用netty作为网络通信框架,netty默认使用-Xmx作为堆外内存大小,调大Xmx 的大小只能延缓堆外内存溢出的时间但是一定会出现异常,我们也可以通过设置-Dio.netty.maxDirectMemory设置堆外内存的大小

点击下选框

 

解决方案:不能使用-Dio.netty.maxDirectMemory去调大堆外内存的大小

①升级lettuce客户端 ②切换使用jedis

使用jedis解决堆外内存溢出

①排除lettuce的依赖

② 使用jedis客户端 *** 控redis

lettuce、jedis都是 *** 作redis的客户端。SpringBoot会再次封装redisTemplate 

SpringBoot会将redisConnectionFactory、redisConnectionFactory封装成RedisConnectionFactory

缓存-缓存使用-缓存击穿、穿透、雪崩

针对缓存穿透、雪崩、击穿的解决方案: 

①对null结果缓存:解决缓存穿透

②设置过期时间(加随机值的过期时间):解决缓存雪崩

③加锁:解决缓存击穿

锁加不好会带来很多问题,下面会讲解如何加锁

缓存-缓存使用-加锁解决缓存击穿的问题

加本地锁的方式

①使用synchronized修饰方法

②使用synchronized代码段

使用this当锁,this指的是当前实现类对象,在SpringBoot中所有组件都是单例的。因此,使用this当锁是可行可以确保所有线程拿的都是同一把锁。

线程拿到锁之后,需要再次判断一下缓存是否命中 

压测一下看下会不会问题:

 

出现问题 : 查询了数据两次

出现问题的原因:当线程1获得锁之后查询数据库,返回查询的结果并释放锁;线程1在将查询的数据存储到redis时,线程2获得锁,发现此时缓存并未命中,因此进行数据库的查询。

解决方案:确认缓存没有、查询数据库、将查询结果存储到redis中是一个原子 *** 作

 

缓存-缓存使用-本地锁在分布式下的问题

存在的问题: 本地锁只能锁住当前的服务,其它服务锁不住

测试:

复制几份product服务,端口号从10000-10003,1右键选择copy configuration...

 

 

查看结果:

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/727863.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存