缓存击穿
假设一个缓存系统中存在一个热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