缓存失效处理需实现平滑热更新且业务无感,核心是可控失效与无缝衔接:一、失效前预热新缓存;二、双缓存+版本路由无缝切换;三、失效期间兜底防穿透击穿;四、业务层容忍陈旧并设计幂等读取。

缓存失效处理要实现平滑热更新且业务无感,关键不是“避免失效”,而是让失效过程可控、可衔接、不引发雪崩或脏读。核心思路是:**用主动刷新替代被动等待,用状态隔离替代强一致性,用渐进替换替代全量切换**。
一、失效前预热新缓存,错开重建窗口
在旧缓存即将过期前(例如提前 30 秒),由后台任务异步加载新版本数据并写入一个带标识的“预热缓存区”(如 Redis key 加后缀 _v2)。此时业务仍读主缓存,但新数据已就位。
- 避免所有请求在同一秒涌向数据库回源
- 预热失败不影响主流程,仅延迟新版本上线
- 可用定时任务或监听数据库 binlog 触发预热
二、双缓存 + 版本路由,无缝切换读源
维护两个逻辑缓存区(如 cache_v1 和 cache_v2),配合一个轻量级版本控制键(如 cache_version:active,值为 "v1" 或 "v2")。读取时先查版本键,再按版本读对应缓存。
- 更新时先写新缓存区,再原子更新版本键(如 Redis 的 SET 命令)
- 切换瞬间只有毫秒级延迟,无缓存未命中
- 旧缓存可保留数分钟用于降级回滚
三、失效期间兜底策略,防止穿透与击穿
即使做了预热和双缓存,仍需应对突发失效或版本键异常。此时不能直接放行所有请求打库。
- 对空查询结果也做短时缓存(如 60 秒),标记为 empty:true,拦截重复穿透请求
- 热点 key 失效时,用分布式锁(如 Redis SETNX)保证只有一个线程回源,其余等待或返回旧值
- 结合布隆过滤器前置校验 ID 合法性,从源头过滤无效请求
四、业务层配合:容忍短暂陈旧,设计幂等读取
真正零感知不只靠缓存机制,更依赖业务语义适配。例如:
- 用户个人中心数据允许 5 秒内陈旧,无需强实时
- 商品详情页价格变动走独立消息通道通知前端刷新,缓存只承载非关键字段
- 所有读接口默认返回 last_updated_at 时间戳,前端可自行判断是否需强制刷新











