什么是缓存击穿、雪崩、穿透

举报
码农小胖哥 发表于 2022/04/01 00:11:57 2022/04/01
【摘要】          随着互联网的越来越普及,用户越来越多,系统性能瓶颈成了越来越热门的话题。要解决性能问题的技术手段有很多,比如:缓存、CDN加速、页面静态化、集群、分布式、异步等。         缓存通常被作为首先技术方案,简单而且提升效...

         随着互联网的越来越普及,用户越来越多,系统性能瓶颈成了越来越热门的话题。要解决性能问题的技术手段有很多,比如:缓存、CDN加速、页面静态化、集群、分布式、异步等。

        缓存通常被作为首先技术方案,简单而且提升效果明显,它能够将速度提升100倍。那么问题来了,缓存为啥会怎么快呢?

        因为传统的数据库操作是基于磁盘的,而缓存是基于内存的,内存操作和磁盘操作的速度根本不是一个数量级的。目前市面上主流的缓存有:redis 和 memcache,这两个都是基于内存的缓存技术,二者的区别我在这里暂时不讲。使用缓存的伪代码一般如下:

        


   
  1. String order = redisClient.get(key);
  2. if(order != null) {
  3.    return order;
  4. }
  5. order = db.get(key);
  6. redisClient.put(key,order);
  7. redisClient.expire(key,3000);
  8. return order;

       根据key获取数据,先从缓存中查一下有没有,如果有则直接返回。如果没有,再从数据库中查到数据,然后将数据放入缓存中,并且给当前key设置一个失效时间,下次再用同样的key来请求数据时,就能够直接从缓存中查询到并返回,减少请求数据库的频次,提升性能,因为数据库连接是稀有资源。

      那么问题又来了,为啥要设置失效时间,不设置不行吗?

      著名的2/8原则告诉我们,经常访问的数据集中在20%,而另外的80%属于不常用数据。我们都知道内存相当于磁盘来说价格是比较昂贵的,不信你买个500G的硬盘 和 一个 500G的内存试试。既然这么贵,我们应该节约使用,所以才会有设置失效时间这种策略,一旦检测到某个key超过了失效时间,就会将该key从缓存中删除,可以节约内存。

    

    还有个问题:如果在某个key失效的时候,有大量的请求一起过来会怎么样?

    这就是我今天要给大家讲的:击穿

    

大量的请求访问同一个key,刚好那个key失效了,那么同一时间所有的请求,都会穿过缓存,直接请求数据库,此时的数据库有可能因为无法扛着这么大的并发,直接挂了。

再问一下:如果大量的请求访问多个key,刚好key同时失效了会怎么样?

    这就是我今天要给大家讲的:雪崩

雪崩比上面的击穿更严重,击穿只是一个key失效了,大量请求直接访问数据库都有可能把数据库搞挂,更何况大量的key同时失效的场景,数据库面临的压力更大,更有可能挂掉。

接下来的问题:如果大量的用户请求缓存中不存在的key又会怎么样?

 这就是我今天要给大家讲的:穿透

有大量的请求访问时,只有少部分的key在缓存中存在,而有大量的key不存在,这样请求也会直接访问到数据库,也会导致数据库扛不住压力而挂掉。这种情况往往是黑客伪造请求,发起的恶意攻击。

那么,这些问题有没有解决办法呢?

首先,击穿的解决办法-加锁

伪代码如下:


   
  1. String order = redisClient.get(key);
  2. if(order != null) {
  3. return order;
  4. }
  5. lock() {
  6. String order = redisClient.get(key);
  7.    if(order != null) {
  8. return order;
  9. }
  10. order = db.get(key);
  11. redisClient.put(key,order);
  12.   redisClient.expire(key,3000);
  13. }
  14. return order;

如果根据key从缓存中查询不到数据,需要从数据库中查询数据的时候,加一把锁,保证同一时间只有一个线程可以查询数据库,然后把查询出来的结果放回到缓存中。这样其他的线程再用相同的key查询时,就可以直接从缓存中查到数据。这样就能够极大的减少数据库的访问频次。

其次,雪崩的解决办法- 加锁 + key设置不同的失效时间

加锁的伪代码跟上面是一样的我就不写了。

雪崩还有一个必要条件就是在同一时间,有大量的key同时失效。我们只要保证不会出现同一时间有大量的key同时失效就可以了,每个key设置不同的失效时间就能解决问题。

最后,穿透的解决办法- 业务规则过滤 + 布隆过滤器

业务规则过滤 可以校验 key的长度或者比如前缀SD开头的等,过滤一批非法数据。

接下来看看布隆过滤器:

布隆过滤器中会初始化数据库中key的标识。如果有大量请求访问不存在的key时,先通过布隆过滤器检查一下key在数据库中是否存在,如果存在才允许访问数据库。如果不存在,则直接返回,这样就可以过滤掉大量的非法请求。

文章来源: felord.blog.csdn.net,作者:码农小胖哥,版权归原作者所有,如需转载,请联系作者。

原文链接:felord.blog.csdn.net/article/details/119306762

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。