缓存穿透(查不存在的数据)
大量请求的Key不存在于缓存中,导致请求直接到数据库上,根本没有经过缓存这一层。一般MySQL默认的最大连接数在150左右,可以通过
show variables like '%max_connections%' ;
查看。一般3000个并发请求就会使大部分数据库宕机。
正常缓存处理流程:
缓存穿透情况处理流程:
解决方案
1. 布隆过滤器
布隆过滤器是一种
数据结构
,对所有可能查询的参数
以hash形式
存储,在控制层先进行校验
,不符合丢弃,从而避免了对底层存储系统的查询压力;
缓存空对象
当缓存层不命中后,即使返回的空对象也将其缓存起来,同时设置一个
过期时间
,之后再访问这个数据将会从缓存中获取,保护了后端数据源。
所存在的问题:
- 缓存需要更多的空间来存储空值的键。
- 即使设置了过期时间,但还是存在
缓存层
和存储层
有段时间窗口不一致,对于需要保持一致性的业务
会有影响。
缓存击穿(大并发+缓存过期)
缓存击穿是指
一个key非常热点
,在不停的扛着大并发,大并发集中对这个key进行访问,当这个key在失效的瞬间,大并发会直接访问数据库,使得数据库瞬间压力过大。
解决方案
设置热点数据永不过期
从缓存层面看,没有设置过期时间,所以不会出现热点key过期后产生的问题
加互斥锁
分布式锁:使用分布式锁,保证对于每个key
同时只有一个线程
去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待,这种方式将高并发的压力转移到了分布式锁,对分布式锁的考验很大。
缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。此后所有的查询都落在了数据库上,对于数据库而言,就会产生周期性的压力,容易产生存储层挂掉。eg:缓存服务器断电
解决方案
redis高可用
搭建集群
限流降级
在缓存失效后,通过加锁或者队列来控制数据库写缓存的线程数量。
数据预热
在正式部署之前,先把可能访问的数据访问一遍,可以将大量的数据加载到缓存中。
《狂神说Java》