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

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. 缓存预热:

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

总结

  • 缓存击穿: 热点数据缓存失效后,大量请求同时查询数据库。解决方案包括互斥锁、缓存预热和合理的过期时间设置。
  • 缓存穿透: 请求的数据在缓存和数据库中都不存在,导致每次请求都直接访问数据库。解决方案包括使用布隆过滤器和缓存空对象。
  • 缓存雪崩: 大量缓存同时失效,导致大量请求同时访问数据库。解决方案包括使用随机过期时间、热点数据缓存和缓存预热。
  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值