性能优化:缓存穿透/击穿/雪崩

3 阅读2分钟

1、性能优化

缓存穿透击穿雪崩是缓存系统中常见的三个问题,会影响系统的性能和稳定性,导致缓存失效或过载。

1.1 缓存穿透

指查询一个不存在的数据,数据既不存在缓存中也不存在数据库中。

解决方案

  1. 缓存空值:查询不存在的数据时,将空值也缓存起来,避免每次都去数据库查询。
  2. 布隆过滤器:拦截不合法的请求,避免访问数据库。布隆过滤器在处理大规模数据时非常高效,且内存占用少,能够有效减少数据库负担。

1.2 缓存击穿

指缓存中某个热点数据的缓存过期,且在这个时刻恰好有大量的请求同时查询这个数据。此时,所有的请求都会去访问数据库,造成数据库压力骤增,甚至宕机。

解决方案

  1. 互斥锁:对热点数据加锁,只有一个线程可以去查询数据库,其他线程会等待或从数据库查询结果中取数据,保证数据库只被查询一次。
使用分布式锁来实现(如Redis的SETNX):
// 线程 A 获取到锁
if (cache.get(key) == null) {
    lock.acquire();  // 获取锁
    // 查询数据库并更新缓存
    lock.release();  // 释放锁
}
  1. 加长缓存过期时间
  2. 双重检查锁:在缓存过期之后,第一次检查缓存,如果缓存为空,则进行数据库查询。查询过程中加锁,只允许一个线程查询数据。其他线程等待缓存更新。

1.3 缓存雪崩

缓存中大量数据在同一时间失效,导致大量请求同时查询数据库。请求量过大,导致数据库宕机或响应变慢。

解决方案

  1. 缓存数据的过期时间分散:对缓存的过期时间进行设置的随机化
  2. 使用缓存预热:在系统启动时或缓存失效时,提前将常用的数据加载到缓存中,避免数据空缺导致的缓存击穿。
  3. 设置合理的缓存过期策略:根据不同的数据设置不同的过期策略,避免所有数据在同一时刻失效。
  4. 使用二级缓存:二级缓存(如 Redis + 本地缓存)可以降低对数据库的直接访问,增强系统容错能力。