缓存雪崩、缓存穿透、缓存击穿是什么,如何应对?
在学习 Redis 时,看到了这个问题,也是面试常问的问题,所以特地以自己的理解记录一下。
首先,前提是系统在数据库的基础上使用了缓存中间件,查询时先查询缓存是否有数据,有的话直接返回缓存里面的数据,没有的话就去数据库查询,查到数据库后存入缓存并返回数据。
缓存雪崩
一般系统都会存在一些热点数据放在缓存中,比如商城系统首页的商品,一般是由定时任务去刷新,在设置时可能会给一批缓存一个固定的过期时间,但是如果恰好缓存同时过期的瞬间来了大量的流量,比如秒杀活动,但是当时所有缓存都失效了,高并发的流量全部进入数据库,数据库扛不住直接崩掉,这个时候如果重启数据库,可能又会被新的流量瞬间打崩,只有等到流量减少到合适时才可以重启。
解决方案:
-
设置过期时间时再加上一个随机值,确保不会同一时间全部失效。
-
设置热点数据永不过期,需要刷新时只需要更新缓存。
缓存击穿
和缓存雪崩类似,但是不一样的是,缓存雪崩是大量热点数据的缓存过期,缓存击穿是指某一个热点数据的缓存过期。当某一个热点数据过期时,大量流量访问该数据的话,会直接去访问数据库,流量非常大的情况下会直接打崩数据库。
解决方案:
-
设置该数据缓存永不过期。
-
访问数据时,加上互斥锁,只允许一个请求访问数据库,其他请求自旋等待缓存,当那一个请求从数据库拿到数据库后再把数据库放到缓存里面。
缓存穿透
如果一条数据在数据库里面是不存在的,那么自然在缓存里面也不会存在。比如所有商品的 id 都是大于 1 的,如果查询 -1或者其他小于0的数据的话,首先查询缓存,发现缓存里面没有,然后就直接去数据库查询,肯定也是查不到的,最后返回空结果,但是下次再次查询这个数据,仍然会走缓存再走数据库,并发量高的情况下很容易把数据库服务器打崩,并且如果没有限制ip等措施,一个机器连续发起请求都足以把一个小型数据库服务器打崩。
解决方案:
首先一定要用Nginx加上 IP 限制,短时间内单 IP 请求超过阈值直接拉黑。
- 空数据也存入缓存(不推荐,产生很多垃圾缓存)
- 查询之前进行校验,非法参数拒绝请求。
- 查询之前加上布隆过滤器。

浙公网安备 33010602011771号