直接回答
缓存击穿指某个热点 key 在过期瞬间,大量并发请求同时发现缓存失效、同时去查数据库并回源,瞬间高并发把 DB 打垮。与穿透的区别:击穿的数据是真实存在的,只是缓存恰好失效。核心解法:互斥锁——只允许一个线程回源重建缓存,其余等待;或逻辑过期——热点 key 不设置 TTL。
展开解析
- 互斥锁(mutex):缓存未命中时先尝试 SETNX 抢锁,抢到锁的线程查 DB、回写缓存、释放锁;没抢到的线程自旋等待后重读缓存。简单有效,注意锁要设超时防止持锁线程挂掉造成死锁。
String v = redis.get(key);
if (v == null) {
if (redis.setnx(lockKey, "1", 10, SECONDS)) {
try { v = db.query(id); redis.set(key, v, ttl); }
finally { redis.del(lockKey); }
} else { Thread.sleep(50); v = redis.get(key); }
}
- 逻辑过期:key 本身不设置物理 TTL,把过期时间存进 value。发现逻辑过期后异步起线程重建,期间先返回旧数据——保证可用性但牺牲短暂一致性。
- 热点 key 不过期:对头部热点人工配置永不过期,由后台任务定时刷新。
追问方向:与雪崩的解法区别、锁粒度选择(按 key 加锁而非全局锁)。