redis缓存穿透、雪崩、击穿
起因
这几天在面试的时候被问到了redis缓存击穿的问题,由于之前只复习到了缓存穿透及缓存雪崩的概念,对缓存击穿没有一个较为清楚的认知和解决方案,故在此进行简单记录。
介绍
- 缓存穿透
所谓缓存穿透指的是大量请求的key根本不存在于缓存中,导致请求没有经过缓存,直接落到了数据库上。这会导致数据库压力过大,甚至宕机,严重时引起整个系统的崩溃。
解决方法:- 缓存空值:当查询数据库为空时,将空值作为缓存值进行缓存,后续请求该key时可以避免再去数据库中查询。但会导致缓存大量无用的空值缓存,消耗内存。
- 布隆过滤器:布隆过滤器是由一个bit数组及若干个哈希函数构成的。当存放元素时由哈希函数对其进行若干次哈希计算,将每个结果对应数组的下标位置置为1。当判断元素是否存在时,同样进行上述操作,如果任意一个位置的值不为1,则此元素一定不存在;但是所有的位置都为1的情况可能会发生误判,此时元素可能存在也可能不存在。
- 对key进行校验:不合法的参数直接拦截。
- 缓存雪崩
某一时刻发生大规模缓存失效的情况,例如缓存服务宕机或者缓存过期时间到了。
解决方案:- 设置随机过期时间:给缓存设置不同的过期时间,防止同一时刻大量缓存失效。
- 定时器刷新缓存:由其他额外服务来定时刷新缓存的过期时间,或者干脆直接设置缓存同步过期。
- 使用ehcache本地缓存+Hystrix限流&降级:本地缓存作为redis缓存不可用时的另一道支撑,同时也可以对接口请求进行限流。
- 缓存击穿
大量请求查询一个热点key时,这个key刚好失效,导致大量的请求落到数据库上。- 设置热点key用不过期:建立缓存时不设置过期时间。
- 互斥锁:当从缓存查询不到数据要去数据库查询时,对查询操作进行加锁,保证同一时刻只有一个线程进行了查库动作,查完库后将值写会到缓存,同时其他获取不到锁的线程可以先原地等待(自旋)再执行获取此热点数据的方法(递归),为了避免发送死循环,最后设置递归的次数。
其他
简单记载了下解决方案,demo待有空研究。
Q.E.D.