一、缓存穿透
1 产生原因
客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会访问数据库。导致DB的压力瞬间变大而卡死或者宕机。
- 大量的高并发的请求打在redis上
- 这些请求发现redis上并没有需要请求的资源,redis命中率降低
- 因此这些大量的高并发请求转向DB请求对应的资源
- DB压力瞬间增大,直接将DB打垮,进而引发一系列“灾害”
缓存穿透发生的场景一般有两类:
- 原来数据是存在的,但由于某些原因(误删除、主动清理等)在缓存和数据库层面被删除了,但前端或前置的应用程序依旧保有这些数据;
- 恶意攻击行为,利用不存在的Key或者恶意尝试导致产生大量不存在的业务数据请求。
2.解决方法
(1)缓存空对象
简单的来说,就是请求之后,发现数据不存在,就将null值打入Redis中。
优点:实现简单,维护方便
缺点:额外的内存消耗
可能造成短期的不一致
思路分析:
当我们客户端访问不存在的数据时,先请求 redis,但是此时 redis 中没有数据,
此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,
我们都知道数据库能够承载的并发不如 redis 这么高,如果大量的请求同时过来访问这种不存在的数据,
这些请求就都会访问到数据库,简单的解决方案就是哪怕这个数据在数据库中也不存在,
我们也把这个数据存入到 redis 中去,这样,下次用户过来访问这个不存在的数据,
那么在 redis 中也能找到这个数据就不会进入到数据库了。
(2)布隆过滤
在客户端与Redis之间加了一个布隆过滤器,对请求进行过滤。
布隆过滤器的大致原理:布隆过滤器中存放二进制位。
数据库的数据通过hash算法计算其hash值并存放到布隆过滤器中,
之后判断数据是否存在的时候,就是判断该hash值是0还是1。
但是这是一种概率上的统计,当其判断不存在的时候就一定是不存在;
当其判断存在的时候就不一定存在。所以有一定的穿透风险
优点:内存占用较少,没有多余 key
缺点:实现复杂 存在误判可能
综上所述qqt
我们可以两种方案一起用,这样子最为保险。据统计使用布隆过滤器一般可以避免90%的无效请求。
二、缓存雪崩
1 产生原因
当redis中的大量key集体过期,可以理解为Redis中的大部分数据都清空 / 失效了,这时候如果有大量并发的请求来到,Redis就无法进行有效的响应(命中率急剧下降),也会导致DB先生的绝望。
缓存雪崩的场景通常有两个:
- 大量热点key同时过期
- 缓存服务故障或宕机
2 解决方法
将失效时间分散开
常用且易于实现通过使用自动生成随机数使得key的过期时间TTL是随机的,防止集体过期。
给业务添加多级缓存
使用nginx缓存 + redis缓存 + 其他缓存,不同层使用不同的缓存,可靠性更强。
构建缓存高可用集群
主要针对缓存服务故障的情景,使用Redis集群来提高服务的可用性。
使用锁或者队列的方式
如果查不到就加上排它锁,其他请求只能进行等待,但这种方式可能影响并发量。
设置缓存标记
热点数据可以不考虑失效,后台异步更新缓存,适用于不严格要求缓存一致性的情景。
三、缓存击穿
1.产生原因
缓存击穿问题也叫热点Key问题,就是⼀个被高并发访问并且缓存重建业务较复杂的key突然失效了,
无数的请求访问会在瞬间给数据库带来巨大的冲击。
2 解决方法
使用互斥锁
只有一个请求可以获取到互斥锁,然后到DB中将数据查询并返回到Redis,之后所有请求就可以从Redis中得到响应。【缺点:所有线程的请求需要一同等待】
”提前“使用互斥锁 / 逻辑过期
在value内部设置一个比缓存(Redis)过期时间短的过期时间标识,当异步线程发现该值快过期时,马上延长内置的这个时间,并重新从数据库加载数据,设置到缓存中去。【缺点:不保证一致性,实现相较互斥锁更复杂】
提前对热点数据进行设置
类似于新闻、某博等软件都需要对热点数据进行预先设置在Redis中,或者适当延长Redis中的Key过期时间。
监控数据,适时调整
监控哪些数据是热门数据,实时的调整key的过期时长。
四、利用互斥锁解决缓存击穿问题
核心思路:
相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是 进行查询之后,
如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果没有得到,
则休眠,过一会再进行尝试,直到获取到锁为止,才能进行查询
如果获取到了锁的线程,再去进行查询,查询后将数据写入 redis,再释放锁,返回数据,
利用互斥锁就能保证只有一个线程去执行操作数据库的逻辑,防止缓存击穿。
441

被折叠的 条评论
为什么被折叠?



