1、性能优化
缓存穿透、击穿、雪崩是缓存系统中常见的三个问题,会影响系统的性能和稳定性,导致缓存失效或过载。
1.1 缓存穿透
指查询一个不存在的数据,数据既不存在缓存中也不存在数据库中。
解决方案:
- 缓存空值:查询不存在的数据时,将空值也缓存起来,避免每次都去数据库查询。
- 布隆过滤器:拦截不合法的请求,避免访问数据库。布隆过滤器在处理大规模数据时非常高效,且内存占用少,能够有效减少数据库负担。
1.2 缓存击穿
指缓存中某个热点数据的缓存过期,且在这个时刻恰好有大量的请求同时查询这个数据。此时,所有的请求都会去访问数据库,造成数据库压力骤增,甚至宕机。
解决方案:
- 互斥锁:对热点数据加锁,只有一个线程可以去查询数据库,其他线程会等待或从数据库查询结果中取数据,保证数据库只被查询一次。
使用分布式锁来实现(如Redis的SETNX):
// 线程 A 获取到锁
if (cache.get(key) == null) {
lock.acquire(); // 获取锁
// 查询数据库并更新缓存
lock.release(); // 释放锁
}
- 加长缓存过期时间
- 双重检查锁:在缓存过期之后,第一次检查缓存,如果缓存为空,则进行数据库查询。查询过程中加锁,只允许一个线程查询数据。其他线程等待缓存更新。
1.3 缓存雪崩
缓存中大量数据在同一时间失效,导致大量请求同时查询数据库。请求量过大,导致数据库宕机或响应变慢。
解决方案:
- 缓存数据的过期时间分散:对缓存的过期时间进行设置的随机化
- 使用缓存预热:在系统启动时或缓存失效时,提前将常用的数据加载到缓存中,避免数据空缺导致的缓存击穿。
- 设置合理的缓存过期策略:根据不同的数据设置不同的过期策略,避免所有数据在同一时刻失效。
- 使用二级缓存:二级缓存(如 Redis + 本地缓存)可以降低对数据库的直接访问,增强系统容错能力。