缓存穿透
什么是缓存穿透?
正常来讲,每次查询数据库时,都会先去缓存中查询是否存在,如果存在则返回,不存在则取查db。
如果去查询数据库不存在的数据,则缓存肯定不存在,那么每次查询都要访问数据库,这就是缓存穿透。
欢迎关注个人公众号【好好学技术】交流学习
会有什么问题呢?
如果大量请求查询数据库不存在的数据,redis也没有缓存,极端情况下,甚至可能造成db宕机,服务不可用。
解决方案
- 1.缓存空值
防止每次请求都去查询db, 我们可以将不存在的数据也缓存一个空值到redis,设置一个可以容忍的过期时间,这样就不会有大量的请求打到db了。 - 2.布隆过滤器
布隆过滤器不了解的同学可以点这里查看
把已存在数据的key存在布隆过滤器中。当有新的请求时,先到布隆过滤器中查询是否存在,如果不存在该条数据直接返回;如果存在该条数据再查询缓存查询数据库。 - 3.加锁
请求数据->查redis不存在->加分布式锁,查询数据库。
当redis缓存没命中时,使用分布式锁可以防止大量请求打到DB,只有拿到锁的第一个请求会去查询数据库。
缓存雪崩
什么是缓存雪崩?
缓存雪崩是指在某一个时间段,缓存集中过期失效。
缓存雪崩带来的问题
缓存雪崩带来的问题也是很可怕的,大量的缓存失效,那么很有可能所有请求都去查询db,极端情况下很有可能导致db宕机,服务不可用。
解决方案
- 1.缓存过期时间加随机因子
根据不同的数据设置不同的过期时间,如果是同一类数据,设置缓存失效时也加上一个随机因子。这样能尽可能分散缓存过期时间。针对热点key,失效时间可以设置长一点时间,甚至永不过期。 - 2.加锁
和缓存穿透加锁方案一样,只要加上锁,那么同一时间就不可能有大量请求去查询数据库,只有拿到锁的第一个请求会去查询数据库。
缓存击穿
什么是缓存击穿?
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。
很多时候容易搞混缓存击穿和缓存穿透,其实只要记着缓存击穿的前提是先击中,才能穿透。 没击中缓存,那就是缓存穿透了。
缓存击穿带来的问题
缓存击穿、穿透、雪崩,带来的问题基本都一样,造成大量请求去查询db,极端情况下很有可能导致db宕机,服务不可用。
解决方案
- 分布式锁
其实分布式锁对缓存穿透、击穿、雪崩都适用。
小结
以上三种情况都是针对缓存异常而引发的问题。导致本应该访问缓存的请求,但是缓存不存在,导致流量全部打到了DB。
针对不同的缓存失效场景,可以选择不同的方案来处理。
当然除了上述方案外,我们也可以使用限流、熔断、降级等来保证服务的可用性。也可以对数据库进行横向扩展,来支撑更多的流量请求。