在计算机系统(尤其是分布式系统)中,缓存击穿是一种常见的缓存异常现象,指的是一个频繁访问的热点缓存key突然失效(过期或被删除),导致大量并发请求瞬间绕过缓存,直接冲击数据库,造成数据库压力骤增,甚至可能引发数据库宕机的情况。
缓存击穿的核心特点
- 目标是热点key:被击穿的缓存key通常是高并发场景下的“热点数据”(如热门商品详情、秒杀活动信息等),访问频率极高。
- 缓存突然失效:可能是缓存key自然过期(如设置了较短的TTL),或被主动删除(如数据更新时误操作)。
- 并发请求“穿透”缓存:缓存失效后,大量并发请求无法从缓存中获取数据,只能直接查询数据库,形成“流量冲击”。
举个例子理解
假设某电商平台的“爆款手机”商品详情页,缓存key为product:10086
,设置了1小时过期。当缓存过期的瞬间:
- 恰好有1000个用户同时访问该商品页;
- 所有请求都发现缓存中没有数据(key已失效);
- 1000个请求同时涌向数据库查询商品信息;
- 数据库可能因瞬间压力过大而响应缓慢,甚至崩溃。
与其他缓存问题的区别
为了更清晰理解,对比另外两种常见缓存异常:
问题类型 | 核心原因 | 区别点 |
---|---|---|
缓存击穿 | 热点key失效,大量并发请求冲击数据库 | 针对单个热点key,因失效引发集中访问 |
缓存穿透 | 请求查询不存在的数据(缓存和数据库都没有) | 针对不存在的key,请求持续穿透到数据库 |
缓存雪崩 | 大量缓存key同时失效,引发数据库整体压力 | 针对多个key批量失效,范围更广 |
如何解决缓存击穿?
核心思路是避免缓存失效后大量请求同时访问数据库,常见方案包括:
设置热点key永不过期
手动管理缓存生命周期,不设置TTL(过期时间),通过业务逻辑主动更新缓存(如商品信息变更时同步更新缓存),从根源避免失效。互斥锁(分布式锁)
当缓存失效时,只允许一个请求获取锁并查询数据库,其他请求等待该请求更新缓存后再从缓存中获取数据。- 流程:请求发现缓存失效 → 尝试获取锁 → 获锁成功:查库并更新缓存 → 获锁失败:等待一段时间后重试(从缓存获取)。
- 工具:可通过Redis的
SETNX
、ZooKeeper等实现分布式锁。
预热热点数据
在缓存过期前,主动触发查询并更新缓存(如定时任务提前刷新热点key),避免“突然失效”的空窗期。熔断降级
当数据库压力过大时,临时返回缓存中的旧数据(即使已过期)或默认值,避免数据库被压垮,待压力缓解后再更新缓存。
通过上述方案,可以有效降低缓存击穿的风险,保障系统在高并发场景下的稳定性。