一、缓存穿透
1、描述
一个一定不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每欠请求都要到存储层去查询,失去了缓存的意义。这个时候很可能就是黑客攻击,可以选择报警处理。
2、场景
1、应用服务器压力变突然大,而redis命中率降低,导致一直查询数据库。
2、出现很多非正常url访问(黑客攻击)
3、解决方案:
1)对空值缓存∶如果一个查询返回的数据为空(不管是数据是否不存在),我
们仍然把这个空结果( null )进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。这也是个短期解决方案
2)设置可访问的名单(白名单) ∶ 使用bitmaps类型定义一个可以访问的名单,名单id作为 bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps 里面,进行拦截,不允许访问。
3)采用布隆过滤器∶(布隆过滤器(Bloom Filter )是1970年由布隆提出的。
它实际上是一个很长的二进制向量(位图)和一系列随机映射函数(哈希函数)。底层就是bitmap原理
二、缓存击穿
1、描述
key对应的数据存在,但在redis 中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
2、场景
数据库压力突然增加,而redis运行正常,也没有出现大量的key过期
3、可能原因
有个别热门key过期,造成数据库突然访问增加。
4、解决方案
1)预先设置热门数据的过期时长。
2)对热门数据做监控,实时调整。
3)用redis锁setnx解决,当获取redis没有数据时候,首先去加抢锁,抢到的先load db,没抢到的等待一段时间再查下,等待说明其他线程在查数据,降低了后端db的访问量。当然效率不高。
返回0,设置不成功,没抢到锁,当然需要加上key的过期时间比较安全。
三、缓存雪崩
1、描述
key对应的数据存在,但在 redis 中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
缓存雪崩与缓存击穿的区别在于这里针对很多key缓存,前者则是某一个key。
2、场景
大量key过期造成数据压力激增。
3、解决方案
1)构建多级缓存:浏览器缓存、nginx缓存、redis缓存等。
2)使用锁机制,但是效率不高,不适用高并发场景
3)提前预知:当key快过期的时候,开启一个线程,重新拉去数据更新失效时间
4)失效时间分散开,比如失效时间的设置为一个范围内的随机值。