缓存系统设计:缓存击穿,缓存雪崩,缓存穿透,缓存预热

缓存击穿

假设一个缓存系统中存在一个热Key,每分每秒都有大量的请求访问这个key,那么当这个热key由于过时而失效,一瞬间全部的请求直接打到DB上,这种场景称作缓存击穿。html

 

为了不这种问题业界通常有以下解决方案缓存

1.互斥锁

当缓存过时时,常见的逻辑是直接请求DB,而后再set回缓存中。为了不缓存击穿的问题,能够在请求DB的地方加一个锁(若是是分布式系统就须要使用分布式锁),争取到锁的就去访问DB,没争取到的就阻塞一段时间再请求缓存,减小直接打到DB的请求。异步

2.永不过时

不给key设置有效期,让key永不过时,而后以定时任务的形式,主动去更新缓存。分布式

3.逻辑过时

一样不给key设置有效期,而是将expired值做为缓存数据的一个字段放入缓存中,取出来时校验一下是否过时,若是过时了则从新设置有效期,并起一个异步线程去更新这缓存。spa

 

缓存雪崩

假设一个缓存系统中,大量的key用的都是同一个expired值,那么在某一瞬间,这些key可能会集体所有失效,全部的请求直接打到DB上,这种场景称做缓存雪崩线程

如何解决?code

1.随机过时时间

将数据写入缓存时每每会设置一个expired值,为了不在某一时间通通所有过时,能够在expired值的基础上加上1~5min的随机值,避免这种状况。这样缓存就不会在某一瞬间忽然所有过时了。htm

 

缓存穿透

当用户访问一个不存在的key时,缓存取不到,按逻辑就是从库里面取,这种请求一多,打到DB的请求也就增长了,这种场景称做缓存击穿。blog

以下,用户不断请求用户信息,但ID都为无效的负数,缓存里面没有,全部请求可能直接打到DB上,若是是恶意请求的话,危害颇大。接口

GET /user/-1 GET /user/-2 .... GET /user/-3

1.缓存不存在的值

若是查询到一个空的结果时,能够仍然将这个空的结果进行缓存,下次在请求的话就会这就返回这个空的结果而不是请求DB。固然,若是这种请求一多,存储里就会存储大量这种无效值,对缓存的空间也是一种压力,因此推荐使用下面BloomFilter的方式。

2.BloomFilter

BloomFilter的特性就是当BloomFilter认为有数据时,是可能有,当认为没有数据时,那就是真没有。故能够利用BloomFilter的特性,挡掉这些不存在的请求。

 

缓存预热 

系统刚启动,缓存还未彻底构建,可是用户不会管这么多,直接一股脑的访问过来,请求又直接打到DB了。若是遇到这种场景,能够利用缓存预热的思想,在系统启动时调用一个后台接口,构建一遍缓存。

原文出处:https://www.cnblogs.com/fudashi233/p/10706750.html

相关文章
相关标签/搜索