缓存穿透、击穿和雪崩
...大约 3 分钟
缓存穿透、击穿和雪崩
缓存的“穿透”,“击穿”,和”雪崩“是什么,怎么解决?
缓存穿透,指大量的请求访问一个不存在的数据,这个数据既不在redis中也不再数据库中,数据库无法正常返回数据,从而导致数据库压力骤增。
缓存穿透的发生主要有两种情况
- 业务操作失误,数据被误删了
- 黑客攻击,大量请求访问不存在的数据
解决方案
方案一:缓存空对象
当从DB查询数据为空,我们仍然将对这个空结果进行缓存,具体的值需要使用特殊的标识,能和真正缓存的数据分开。另外,需要设置较短的过期时间,一般建议不要超过5分钟
方案二:布隆过滤器(BloomFilter)
在缓存服务的基础上,构建BloomFilter 数据结构,在BloomFilter中储存对应的Key是否存在,如果存在,说明该Key对应的值不为空
方案三:非法请求的限制
在API入口处对请求参数进行判断是否合法,拒绝恶意的请求
缓存雪崩,是指大量缓存数据同一时间过期或者redis故障宕机时,大量请求在redis中无法处理,全都访问到数据库,导致数据库、系统崩溃。
对于不同的诱因,有不同的策略
- 大量数据同时过期
- 均匀设置过期时间:给缓存的数据设置一个不同的过期时间
- 互斥锁:当发现受访问的数据不在redis中,就加个互斥锁(要加上过期时间),保证同一时间内只有一个请求来构建缓存,构建完成后再释放锁
- 后台更新缓存:可以通过消息队列给后台发送消息,进行更新缓存,让缓存“永久有效”
- redis宕机:服务熔断或者请求限流:暂停业务,请求直接返回错误或者对请求进行限流
- 构建redis缓存高可靠集群:采用主从节点切换的方式,主节点发生故障,换成从节点
- 大量数据同时过期
缓存击穿,是指某个季度“热点”数据在某个时间点过期时,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从DB加载数据并回设到缓存,但是这个时候大并发的请求可能会瞬间DB压垮。对于一些设置了过期时间的Key,如果这些Key可能会在某些时间点背超高并发第访问,是一种非常“热点”的数据。这个时候,需要考虑这个问题。
区别:
和缓存“雪崩”的区别在于,前者针对某一Key缓存,后者则是很多Key
和缓存“穿透”的区别在于,这个Key是真实存在对应的值的
有两种方案可以解决:
- 使用互斥锁。请求发现缓存不存在后,去查询DB前,使用分布式锁,保证有且只有一个线程去查询DB,并更新到缓存
- 手动过期,缓存上不设置过期时间