首页 > 其他分享 >什么是缓存击穿、缓存穿透、缓存雪崩?

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

时间:2024-08-13 13:54:09浏览次数:14  
标签:缓存 请求 过期 数据库 击穿 雪崩 data String

1. 缓存击穿 (Cache Breakdown)

定义: 缓存击穿指的是缓存中某个热点数据在过期或被删除后,突然失效,导致大量请求同时到达数据库。由于热点数据的缓存失效,这些请求会同时直接访问数据库,导致数据库负载急剧增加。

具体场景: 假设一个电商平台的一个热销商品的库存信息被缓存了。如果这个商品的缓存因为过期或者被清除,而在短时间内有大量用户同时访问这个商品的库存信息,所有请求都会查询数据库。由于数据库需要处理大量的请求,可能会导致数据库性能下降,甚至崩溃。

解决方案:

  1. 互斥锁:

    • 当缓存失效时,使用互斥锁确保只有一个请求去加载数据并更新缓存。其他请求会在获取锁后等待数据加载完成,避免了多个请求同时访问数据库。
    • 示例代码(使用 Redis 锁):
      import redis.clients.jedis.Jedis;
      import redis.clients.jedis.JedisPool;
      import java.util.concurrent.TimeUnit;
      
      public class CacheService {
          private JedisPool jedisPool = new JedisPool("localhost");
      
          public void getData(String key) {
              Jedis jedis = jedisPool.getResource();
              try {
                  // 尝试获取锁
                  String lockKey = "lock:" + key;
                  String lockValue = String.valueOf(System.currentTimeMillis() + 5000);
                  String result = jedis.set(lockKey, lockValue, "NX", "PX", 5000);
      
                  if ("OK".equals(result)) {
                      // 锁获取成功,查询数据库
                      String data = queryDatabase(key);
                      jedis.set(key, data);
                  } else {
                      // 锁获取失败,等待锁释放
                      TimeUnit.SECONDS.sleep(1);
                      // 再次尝试获取数据
                      getData(key);
                  }
              } catch (InterruptedException e) {
                  e.printStackTrace();
              } finally {
                  jedis.close();
              }
          }
      
          private String queryDatabase(String key) {
              // 模拟数据库查询
              return "data";
          }
      }
      

  2. 缓存预热:

    • 在缓存数据即将过期前,提前更新缓存。可以在应用启动时或定期更新缓存数据,避免大量请求在缓存失效后集中到数据库。
  3. 合理设置过期时间:

    • 根据数据的使用频率和业务需求设置合理的缓存过期时间。避免热点数据的缓存过期时间设置过短。

2. 缓存穿透 (Cache Penetration)

定义: 缓存穿透发生在缓存无法拦截某些请求,这些请求绕过缓存直接访问数据库。通常发生在请求的数据在缓存和数据库中都不存在,导致每次请求都访问数据库。

具体场景: 例如,用户请求的商品ID不存在于数据库中。缓存没有记录这种不存在的情况,导致每次请求都直接查询数据库,造成数据库的无效请求增加。

解决方案:

  1. 布隆过滤器:

    • 使用布隆过滤器来检查请求的数据是否可能存在于数据库中。布隆过滤器可以有效地拦截不可能存在的数据,避免无效请求到达数据库。
    • 示例代码(Java):
      import com.google.common.hash.BloomFilter;
      import com.google.common.hash.Funnels;
      
      public class BloomFilterExample {
          private BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.unencodedCharsFunnel(), 10000);
      
          public void addData(String data) {
              bloomFilter.put(data);
          }
      
          public boolean mightContain(String data) {
              return bloomFilter.mightContain(data);
          }
      }
      

  2. 缓存空对象:

    • 对于查询结果为空的数据,将“空结果”缓存起来,并设置较短的过期时间,以减少对数据库的访问。例如,缓存一个表示不存在的对象。

3. 缓存雪崩 (Cache Avalanche)

定义: 缓存雪崩指的是大量缓存数据在同一时间过期,导致大量请求同时访问数据库,从而造成数据库负载急剧增加。这通常发生在多个缓存项设置了相同的过期时间,或缓存系统出现故障时。

具体场景: 例如,多个缓存项设置了相同的过期时间(如每小时过期),在过期时刻所有缓存项同时失效,导致所有请求同时访问数据库,可能导致数据库压力过大。

解决方案:

  1. 使用随机过期时间:

    • 为缓存数据设置随机的过期时间,以避免大量缓存项在同一时间过期。可以在缓存数据的过期时间上增加一个随机偏移量。
  2. 热点数据缓存:

    • 对于访问频率极高的热点数据,使用特殊的缓存策略,如增加缓存的过期时间或使用额外的缓存层。
  3. 缓存预热:

    • 在系统启动或缓存失效时提前加载数据,减少数据库负载。可以在系统启动时从数据库中加载数据到缓存中,或者定期刷新缓存。

总结

  • 缓存击穿: 热点数据缓存失效后,大量请求同时查询数据库。解决方案包括互斥锁、缓存预热和合理的过期时间设置。
  • 缓存穿透: 请求的数据在缓存和数据库中都不存在,导致每次请求都直接访问数据库。解决方案包括使用布隆过滤器和缓存空对象。
  • 缓存雪崩: 大量缓存同时失效,导致大量请求同时访问数据库。解决方案包括使用随机过期时间、热点数据缓存和缓存预热。

标签:缓存,请求,过期,数据库,击穿,雪崩,data,String
From: https://blog.csdn.net/m0_57083961/article/details/141070338

相关文章

  • windwos清理图标缓存
    有的时候桌面图标突然就没了,可以采用下面bat命令进行清理rem关闭Windows外壳程序explorertaskkill/f/imexplorer.exerem清理系统图标缓存数据库attrib-h-s-r"%userprofile%\AppData\Local\IconCache.db"del/f"%userprofile%\AppData\Local\IconCache.db"a......
  • jetcache缓存使用
    1、简介​ jetcache是阿里开源的一个缓存框架,支持像guava的cache、caffeine的Cache用法,也可以集成springboot,像spring的@Cache注解一样进行使用。​ jetcache的缓存类似于map,提供了get、put、putAll、computeIfAbsent等方法,另外还提供了单机锁、分布式锁机制,一般也不用这个......
  • .NET8 缓存的使用
    .NET8下面的几种缓存的使用。(1)ICache.cs   usingSystem;usingSystem.Threading.Tasks;publicinterfaceICache{#region设置缓存///<summary>///设置缓存///</summary>///<paramname="key"&......
  • Redis实际项目中涉及缓存一致性的处理
    在实际项目中,Redis缓存一致性是一个关键问题,尤其是在分布式系统中。缓存一致性指的是确保缓存中的数据与实际数据库中的数据保持同步。以下是一些在实际项目中处理Redis缓存一致性的方法和最佳实践:1.缓存失效策略a.TTL(TimetoLive):设置缓存的过期时间。当数据过期后,缓存会自......
  • 如何使用Memcached缓存图片信息
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......
  • 【Redis进阶】缓存设计模式
    目录CacheAside(旁路缓存)模式概念读操作流程如上图所示写操作流程如上图所示代码示例总结Read-Through模式概念操作流程:优点:Write-Through模式概念操作流程:优点:Write-Behind(Write-Back)模式概念操作流程:优点:缺点:总结缓存设计模式是指将缓存作为系统架......
  • 节假日配置初始化 redis缓存方案及@PostConstruct注解,Cache方案GuavaUtils.java工具类
    节假日配置初始化redis缓存方案及@PostConstruct注解,Cache方案GuavaUtils.java工具类启动报错:本机,在jenkins上面没有报错?包括嵌套的注入Beanjava静态代码块和spring@value等注解注入顺序https://www.cnblogs.com/oktokeep/p/15530697.html/***节假日配置初始化redis缓存......
  • Redis5-缓存
    目录什么是缓存添加Redis缓存缓存更新策略三种策略数据库和缓存不一致的解决方案缓存穿透缓存雪崩缓存击穿缓存工具封装什么是缓存缓存是数据交换的缓冲区(Cache),是存贮数据的临时地方,一般读写性能较高多级缓存:浏览器缓存:主要是存在于浏览器端的缓存应用层缓存:可以......
  • Java中的灵活缓存失效策略设计:从TTL到LRU的实现
    Java中的灵活缓存失效策略设计:从TTL到LRU的实现大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!缓存失效策略在现代应用程序中至关重要,它决定了缓存数据的更新和淘汰机制。本文将探讨在Java中如何实现灵活的缓存失效策略,包括TTL(Time-To-Live)和LRU(Le......
  • 手写Redis缓存系统,第一章:基于http协议实现的缓存系统
    关系描述关系图文本描述main包依赖cache包依赖http包流程:main包的main函数调用cache.New("inmemory")创建一个缓存实例。main包的main函数将缓存实例传递给http.New(c)创建一个Server实例。Server实例调用Listen方法启动HTTP服务器......