缓存穿透、雪崩、击穿

缓存穿透、缓存雪崩和缓存击穿是分布式系统中常见的缓存问题,它们都会导致缓存失效,进而对数据库或其他底层存储系统造成压力。以下是它们的详细说明及解决方案:


1. 缓存穿透(Cache Penetration)

定义

缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,请求会直接落到数据库上。如果大量请求同时查询不存在的数据,数据库可能会被压垮。

原因
  • 恶意攻击:攻击者故意查询不存在的数据。
  • 业务逻辑问题:程序逻辑错误,导致频繁查询不存在的数据。
解决方案
  1. 缓存空值

    • 如果查询结果为空,仍然将空值缓存起来,并设置一个较短的过期时间。
    • 示例:
      if (data == null) {
          cache.put(key, NULL_VALUE, 60); // 缓存空值,过期时间 60 秒
      }
      
  2. 布隆过滤器(Bloom Filter)

    • 使用布隆过滤器判断数据是否存在。如果布隆过滤器判断数据不存在,则直接返回,避免查询数据库。
    • 示例:
      if (!bloomFilter.mightContain(key)) {
          return null; // 数据不存在,直接返回
      }
      
  3. 接口层校验

    • 在接口层对请求参数进行校验,过滤掉非法请求。

2. 缓存雪崩(Cache Avalanche)

定义

缓存雪崩是指大量缓存同时失效,导致所有请求都落到数据库上,数据库压力骤增,甚至崩溃。

原因
  • 缓存设置了相同的过期时间。
  • 缓存服务器宕机。
解决方案
  1. 设置不同的过期时间

    • 在设置缓存过期时间时,增加一个随机值,避免大量缓存同时失效。
    • 示例:
      int expireTime = 3600 + new Random().nextInt(600); // 过期时间在 3600~4200 秒之间
      cache.put(key, value, expireTime);
      
  2. 缓存高可用

    • 使用 Redis 集群或其他高可用方案,避免单点故障。
  3. 限流和降级

    • 使用限流工具(如 Sentinel、Hystrix)限制数据库的请求量。
    • 在缓存失效时,返回默认值或错误提示,避免直接访问数据库。
  4. 缓存预热

    • 在系统启动时,提前加载热点数据到缓存中。

3. 缓存击穿(Cache Breakdown)

定义

缓存击穿是指某个热点数据过期,同时有大量请求访问该数据,导致请求直接落到数据库上。

原因
  • 热点数据过期。
  • 大量请求同时访问该热点数据。
解决方案
  1. 互斥锁(Mutex Lock)

    • 在缓存失效时,使用分布式锁(如 Redis 的 SETNX)保证只有一个线程去查询数据库,其他线程等待。
    • 示例:
      String value = cache.get(key);
      if (value == null) {
          if (lock.tryLock()) { // 获取分布式锁
              try {
                  value = db.get(key); // 查询数据库
                  cache.put(key, value); // 更新缓存
              } finally {
                  lock.unlock(); // 释放锁
              }
          } else {
              Thread.sleep(100); // 等待一段时间后重试
              return getData(key); // 重试
          }
      }
      
  2. 永不过期

    • 对热点数据设置永不过期,通过后台任务定期更新缓存。
    • 示例:
      cache.put(key, value); // 永不过期
      
  3. 逻辑过期

    • 在缓存中存储数据的过期时间,而不是依赖缓存的过期机制。当数据过期时,异步更新缓存。
    • 示例:
      if (cache.getExpireTime(key) < System.currentTimeMillis()) {
          // 异步更新缓存
          executor.submit(() -> {
              String newValue = db.get(key);
              cache.put(key, newValue);
          });
      }
      

4. 总结

问题定义原因解决方案
缓存穿透查询不存在的数据,请求落到数据库恶意攻击或业务逻辑问题缓存空值、布隆过滤器、接口层校验
缓存雪崩大量缓存同时失效,请求落到数据库缓存设置相同过期时间或缓存服务器宕机设置不同过期时间、缓存高可用、限流降级
缓存击穿热点数据过期,大量请求落到数据库热点数据过期互斥锁、永不过期、逻辑过期

5. 面试回答建议

在面试中回答这个问题时,可以按照以下思路:

  1. 分别解释缓存穿透、缓存雪崩和缓存击穿的定义和原因。
  2. 结合实际项目经验,举例说明如何解决这些问题。
  3. 强调解决方案的适用场景(如布隆过滤器适合缓存穿透,互斥锁适合缓存击穿)。

这样回答既展示了你的技术深度,也体现了你对缓存问题的理解和解决能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huingymm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值