面试中比较频繁问之一,首先得知道它的概念:用户想要访问一个数据,发现Redis内存数据没有(也就是缓存没有命中),于是向持久层数据库访问,发现数据库中也没有,这次访问就算是失败。
这时如果很多用户访问,缓存中没有命中,都直接请求数据库,就造成数据库压力很大。这时就出现缓存穿透。缓存没有起到作用,很多访问直接访问数据库。
(1)对空值缓存
如果一个查询返回的数据为空,(查询为空的数据,在Redis也查不到)仍然把这个空结果(null)进行缓存,设置空结果的过期时间(最好设置为五分钟),之后再次访问这个数据将会从缓存中获取,保护了后端数据源。
(2)采用布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,控制层先进行校验,可以检索一个元素是否在一个集合中;不符合则就丢弃,从而避免对底层存储系统的查询压力。
这个缓存穿透有区别的,缓存击穿:是指一个key非常热点,在不停的扛着大并发,大并发集中对这个key进行访问,当这个key突然失效的瞬间(缓存设置的过期时间,好比淘宝在特点时间搞活动),有大量并发就会穿破缓存,直接访问数据库;导致数据库的压力瞬间过大。很有可能数据库宕机。
(1)预先设置热门数据
在Redis高峰访问之前,把一些热门数据提前存入Redis中,并且加大这些热门数据key的时长
(2)使用锁
缓存雪崩:指在某一个时间段,缓存集中过期失效。Redis宕机。
比如在双十一0点活动,一些商品集中存放到缓存;假设一个小时后(凌晨一点结束)缓存都过期。卡点再次对这些商品访问,都会直接访问数据库上,对于数据库压力相当大,很可能数据库直接宕机。
其实集中过期,倒不是非常致命,比较致命缓存雪崩是缓存服务器在某个节点宕机或者断网。
(1)构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)
(2)使用锁或队列
用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。
(3)将缓存失效时间分散开
可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
缓存穿透:是在 缓存 和 数据库 都查不到
缓存击穿:是 量太大 缓存过期(某一个键值过期)
缓存雪崩 和 缓存击穿 的区别 : 缓存雪崩式很多key过期 缓存击穿 是 某一个key过期。