zoukankan      html  css  js  c++  java
  • 缓存穿透、缓存击穿、缓存雪崩区别和解决方案

    本文由 简悦 SimpRead 转码, 原文地址 zhuanlan.zhihu.com

    前言

    Redis 作为目前使用最广泛的缓存,相信大家都不陌生。但是使用缓存并没有这么简单,还要考虑缓存雪崩,缓存击穿,缓存穿透的问题,什么是缓存雪崩,击穿,穿透呢,出现这些问题又怎么解决呢,接下来学习一下吧。

    缓存雪崩

    什么是缓存雪崩?

    当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机。这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死。这就是缓存雪崩。

    分析:

    造成缓存雪崩的关键在于在同一时间大规模的 key 失效。为什么会出现这个问题呢,有几种可能,第一种可能是 Redis 宕机,第二种可能是采用了相同的过期时间。搞清楚原因之后,那么有什么解决方案呢?

    解决方案:

    1、在原有的失效时间上加上一个随机值,比如 1-5 分钟随机。这样就避免了因为采用相同的过期时间导致的缓存雪崩。

    如果真的发生了缓存雪崩,有没有什么兜底的措施?

    2、使用熔断机制。当流量到达一定的阈值时,就直接返回 “系统拥挤” 之类的提示,防止过多的请求打在数据库上。至少能保证一部分用户是可以正常使用,其他用户多刷新几次也能得到结果。

    3、提高数据库的容灾能力,可以使用分库分表,读写分离的策略。

    4、为了防止 Redis 宕机导致缓存雪崩的问题,可以搭建 Redis 集群,提高 Redis 的容灾性。

    缓存击穿

    什么是缓存击穿?

    其实跟缓存雪崩有点类似,缓存雪崩是大规模的 key 失效,而缓存击穿是一个热点的 Key,有大并发集中对其进行访问,突然间这个 Key 失效了,导致大并发全部打在数据库上,导致数据库压力剧增。这种现象就叫做缓存击穿。

    分析:

    关键在于某个热点的 key 失效了,导致大并发集中打在数据库上。所以要从两个方面解决,第一是否可以考虑热点 key 不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量。

    解决方案:

    1、上面说过了,如果业务允许的话,对于热点的 key 可以设置永不过期的 key。

    2、使用互斥锁。如果缓存失效的情况,只有拿到锁才可以查询数据库,降低了在同一时刻打在数据库上的请求,防止数据库打死。当然这样会导致系统的性能变差。

    缓存穿透

    什么是缓存穿透?

    我们使用 Redis 大部分情况都是通过 Key 查询对应的值,假如发送的请求传进来的 key 是不存在 Redis 中的,那么就查不到缓存,查不到缓存就会去数据库查询。假如有大量这样的请求,这些请求像 “穿透” 了缓存一样直接打在数据库上,这种现象就叫做缓存穿透。

    分析:

    关键在于在 Redis 查不到 key 值,这和缓存击穿有根本的区别,区别在于缓存穿透的情况是传进来的 key 在 Redis 中是不存在的。假如有黑客传进大量的不存在的 key,那么大量的请求打在数据库上是很致命的问题,所以在日常开发中要对参数做好校验,一些非法的参数,不可能存在的 key 就直接返回错误提示,要对调用方保持这种 “不信任” 的心态。

    解决方案:

    1、把无效的 Key 存进 Redis 中。如果 Redis 查不到数据,数据库也查不到,我们把这个 Key 值保存进 Redis,设置 value="null",当下次再通过这个 Key 查询时就不需要再查询数据库。这种处理方式肯定是有问题的,假如传进来的这个不存在的 Key 值每次都是随机的,那存进 Redis 也没有意义。

    2、使用布隆过滤器。布隆过滤器的作用是某个 key 不存在,那么就一定不存在,它说某个 key 存在,那么很大可能是存在 (存在一定的误判率)。于是我们可以在缓存之前再加一层布隆过滤器,在查询的时候先去布隆过滤器查询 key 是否存在,如果不存在就直接返回。

    总结

    这三个问题在使用 Redis 的时候是肯定会遇到的,而且是非常致命性的问题,所以在日常开发中一定要注意,每次使用 Redis 时,都要对其保持严谨的态度。还有一个需要注意的是要做好熔断,一旦出现缓存雪崩,击穿,穿透这种情况,至少还有熔断机制保护数据库不会被打死。

     

  • 相关阅读:
    Java基础面试操作题: 线程问题,写一个死锁(原理:只有互相都等待对方放弃资源才会产生死锁)
    Java基础面试操作题: File IO 文件过滤器FileFilter 练习 把一个文件夹下的.java文件复制到另一个文件夹下的.txt文件
    Java基础面试操作题:Java代理工厂设计模式 ProxyFactory 有一个Baby类,有Cry行为,Baby可以配一个保姆 但是作为保姆必须遵守保姆协议:能够处理Baby类Cry的行为,如喂奶、哄睡觉。
    Java中 Character方法练习:字符串中英文字母个数 5435abc54abc3AHJ5 正则:matches("[a-zA-Z0-9]{1}")
    Java 练习:字符串反转
    集合类别
    JAVA 后台
    micro focus cobol vs mainframe cobol
    Java 编码
    关于java中char占几个字节,汉字占几个字节
  • 原文地址:https://www.cnblogs.com/Gaimo/p/15008336.html
Copyright © 2011-2022 走看看