缓存击穿是怎么回事
你有没有遇到过这种情况:网站平时访问挺快,突然之间卡得不行,数据库直接被打满,运维一查日志发现大量请求绕过了缓存,直奔数据库?这很可能就是缓存击穿在作怪。
缓存击穿指的是某个热点数据在缓存中过期的瞬间,大量并发请求同时发现缓存里没有,于是全都去查数据库。数据库扛不住这么猛的冲击,响应变慢甚至崩溃,用户体验直线下降。
为什么会发生缓存击穿
最常见的场景是某个爆款商品的详情页。比如双11期间,一款限量手机的页面被疯狂刷新。这个页面的数据存在缓存里,设置的过期时间是10分钟。第10分钟一到,缓存失效,下一波请求进来发现缓存空了,成千上万的请求同时涌向数据库,服务器立马吃不消。
问题的关键在于:缓存失效 + 高并发 + 热点数据。这三个条件凑一块儿,就容易出事。
怎么防止缓存击穿
最直接的办法是给热点数据加互斥锁。第一个没查到缓存的请求,去数据库取数据的同时,其他请求等着。等数据重新写回缓存,大家再从缓存拿。这样避免了重复查询数据库。
比如用 Redis 做缓存时,可以用 SETNX 命令实现简单锁:
SETNX cache_key_lock 1 // 尝试加锁
if (成功) {
data = query_db();
set_cache(cache_key, data, 3600);
del(cache_key_lock);
} else {
sleep(100); // 等一会儿再查缓存
data = get_cache(cache_key);
}另一种办法是延长热点数据的过期时间,或者干脆不设过期,靠主动更新来维护。比如后台改了商品价格,立刻同步到缓存,而不是等它过期。
还可以提前刷新缓存。在缓存快要过期前,后台线程自动去更新,保证缓存始终有效。这种方式叫“缓存永不过期”策略,适合变化不频繁但访问量大的数据。
实际应用中,往往是多种手段结合。比如大促期间,热门商品页用永不过期 + 主动更新,普通页面用过期 + 互斥锁兜底,既保证性能又节省内存。