目录
2.缓存穿透?(顾名思义没有通过缓存作为盾。直接到了DB上了)
3.缓存击穿?(缓存没有数据库有,但是并发很大,都相差一个热点数据,然后同时去数据库取)
1.缓存雪崩?(DB被大量的过期key查询查挂掉了)
缓存过期时间设置的不好,而导致大批量的缓存过期,导致都要去查数据库,数据库的压力就会极大。
解决办法:1.缓存过期时间再加上一个分钟的随机数
2.查询数据库的时候,要先拿到分布式锁。避免把数据库雪崩。(因为是集体失效,所以叫做雪崩)
高并发场景下应该减少使用,强制加锁的办法。(因为用户比如999人还要拿到数据库数据的)
3.设置过期标志更新缓存,也就是查询过期标志和真正缓存。这两个有个时间差,如果发现标志过期了,那么依然返回旧数据给调用者,同时开启线程,更新这个数据,知道更新完成返回新的数据。(这边还会有更新时候的锁,不用重复更新)
4.二级缓存?做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期(此点为补充)
2.缓存穿透?(顾名思义没有通过缓存作为盾。直接到了DB上了)
如果key对应的value是一定不存在的,并且对该key并发请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
解决方案:1. 对查询为空的缓存也进行缓存就好了。缓存时间设置短一点。或者如果这个KEY真的存在数据了,那么删除这个空的value
2.对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。
(BitMap可以单独学一学,因为也是redis中很常见的内容。)
3.缓存击穿?(缓存没有数据库有,但是并发很大,都相差一个热点数据,然后同时去数据库取)
在高并发下,对一个特定的值进行查询,但是这个时候缓存正好过期了,缓存没有命中,导致大量请求直接落到数据库上,如活动系统里面查询活动信息,但是在活动进行过程中活动缓存突然过期了。
与缓存穿透相比,是查询一个特定的值,是存在的,但是大量请求就来到了数据库了。
解决办法:1.设置热点数据永远不过期。
2. 假如互斥锁,使用reenlock,如果获取成功,那么去数据库取得数据,没有的话再次暂停100ms再去取。
4. 缓存的预热?(上线前一定会做的事情)
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。
在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
写个Junit进行手动加载就好了,或者做个定时定时刷新缓存。
5.缓存的更新?
没什么好说的,其实就是从DB查询再放到缓存中。
6.缓存的降级?
跟服务的降级,做对比。
缓存降级,其实也是相对来说保证核心系统可以用,即使是有损的。有些服务不能降级,涉及到订单和购物和金钱等等。
比如秒杀服务的降级,可以只对cache先做更新,然后再去异步队列或者别的方式同步到数据库的库存信息。
保证最终的数据库一致性。
读降级
比如多级缓存模式,如果后端服务有问题,可以降级为只读缓存,这种方式适用于对读一致性要求不高的场景;
降级的概念:就是在高并发高负载情况下,选择动态的关闭一下不重要的服务,拒绝访问等,来为重要的服务节省资源,比如电商平台秒杀当天可关闭推荐等功能。
7.缓存并发?
这里的并发指的是多个redis的client同时setkey引起的并发问题。其实redis自身就是单线程操作,多个client并发操作,按照先到先执行的原则,先到的先执行,其余的阻塞。当然,另外的解决方案是把redis.set操作放在队列中使其串行化,必须的一个一个执行。