不用复杂方案,一个互斥锁就能轻松解决,代码简单、生产稳定、新手也能看懂。
一、什么是缓存击穿
简单说就是:某个非常热点的 Key 突然过期了。这一瞬间,大量请求同时涌进来,发现缓存里没有数据,就会全部直接打到数据库。数据库压力瞬间拉满,轻则查询变慢,重则直接被打崩。
二、最简解决方案:互斥锁
核心思路就一句话:只让一个请求去查库,其他请求等着,避免数据库被冲垮。
直接上代码:
public Object getCache(String key) {
// 1. 先查缓存
Object cache = redisTemplate.opsForValue().get(key);
if (cache != null) {
return cache;
}
// 2. 加锁,只允许一个请求去查库
String lockKey = "lock:" + key;
Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (Boolean.TRUE.equals(lock)) {
try {
// 3. 只有拿到锁的请求,才去查询数据库
Object data = dbService.getData(key);
// 4. 查询完成,把数据写回缓存
redisTemplate.opsForValue().set(key, data, 5, TimeUnit.MINUTES);
return data;
} finally {
// 5. 最后一定要释放锁,避免死锁
redisTemplate.delete(lockKey);
}
}
// 6. 没拿到锁的线程,稍等一下再重试
ThreadUtil.sleep(100);
return getCache(key);
}
三、方案优点
四、避坑
- 锁必须加过期时间,否则出现异常会导致死锁
- 缓存过期时间最好加一个随机值,避免大量 Key 同时失效
- 真正的热点 Key,可以直接设置永久缓存,从根源避免击穿
缓存击穿是 Redis 最常考、也最常遇到的问题。掌握这个简单实用的方案,面试能讲清楚,生产能直接用,再也不用担心数据库被瞬间打崩。






