<返回更多

怎样应对缓存穿透?

2019-11-12    
加入收藏

1为什么需要缓存

  1. 如果没有缓存,那么所有业务请求会直接指向数据库,以MySQL为例的数据库基本都是基于磁盘的,而磁盘I/O开销大,面对大规模请求时,会降低系统性能。
  2. 对一些热点数据,将其从数据库中抽离出来放进缓存,每次查询时先走缓存,缓存命中则直接返回结果,能提高效率。

2缓存带来的问题

有三个经典问题:

  1. 缓存雪崩:指缓存大面积失效,导致大量查询落到了数据库上,使数据库挂掉。
  2. 缓存击穿:缓存中热点key突然失效,原本走缓存的大量请求直接打向了数据库,就好像在缓存中击穿了一个洞。
  3. 缓存穿透:用户一直请求缓存和数据库都不存在的数据,每次请求缓存不命中,数据库也不命中,就像缓存不存在一样,同时不断地请求也给数据库带来压力。

3应对方案

这里主要介绍 缓存穿透 的解决方案,先看两幅原理图。

用户请求大致原理图:

怎样应对缓存穿透?

 

用户发出请求后先查缓存,缓存命中则直接返回;

缓存不命中就查数据库,查到后将数据写入缓存并返回给用户。

用户请求缓存和数据库都没有的数据(即缓存穿透,如请求id=-1的数据):

怎样应对缓存穿透?

 

此时缓存基本失去了作用。

常见的解决思路:

将用户请求的不存在的数据也放进缓存,并将值置为null,这样请求走缓存的时候发现结果为null,直接返回即可。

但是需要给缓存中的key设置一个合适的过期时间,否则数据库中有了这样的数据,就会出现 数据不一致 问题。

更好的解决思路:

使用 布隆过滤器(Bloom Filter) 。 它可用于快速判断数据是否存在于某个集合中,借助这个功能,我们可用它来应对缓存穿透。

回顾一下布隆过滤器的两条重要特性:

1. 布隆过滤器判定数据存在,那么它可能存在也可能不存在。

2. 布隆过滤器判定数据不存在,那么它一定不存在。

加上布隆过滤器之后:

怎样应对缓存穿透?

 

用户请求数据,若Bloom Filter返回false,则直接过滤该请求或返回null;若 Bloom Filter 返回true,则查缓存,缓存命中则返回,不命中则查数据库。

Bloom Filter 就好像是加在缓存前的一道 屏障 ,过滤了几乎所有不符合要求的请求。虽然有一定的误判率,即可能有少数通过了 Blo om Filter 的请求在数据库和缓存中也还是不命中,但相比之下,整个系统性能已经大大提升,且 Blo om Filter 的默认误判率只有0.03.

顺带提一下缓存击穿和缓存雪崩的解决方案。

缓存击穿:

在被查询的数据上加互斥锁,一条请求线程拿到锁后其它线程只能等待。

缓存雪崩:

事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。

事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉。

事后:利用 redis 持久化机制保存的数据尽快恢复缓存。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>