最近在做缓存更新可靠性测试时,踩了一个大坑。项目中采用的是Cache-Aside模式,写操作先更新DB再删除缓存,看似完美,但在高并发场景下出现了数据不一致问题。
问题复现步骤:
- 同时发起100个写请求,每个请求都先更新DB再删除缓存
- 在删除缓存后、重新加载缓存前的短暂窗口期,读请求会命中旧缓存
- 某些请求在删除缓存后因网络抖动超时,但DB更新已成功
- 最终导致DB数据新,但缓存中仍是旧数据
核心问题: 传统双写机制在失败恢复时缺乏原子性。当DB更新成功而缓存删除失败时,系统处于不一致状态。
解决方案尝试:
- 引入分布式锁控制并发更新,但增加了延迟
- 使用消息队列异步清理缓存,但引入了最终一致性
- 最终采用Redis的TTL机制+重试策略,在缓存失效前完成双写
代码示例(伪代码):
if (db.update(data)) {
// 延迟删除缓存或使用消息队列
asyncCacheDelete(key);
// 或者设置较短的TTL,让其自然过期
redis.setex(key, ttl, value);
}
这个坑踩得真够惨的,建议大家在生产环境一定要做这种失败场景测试。

讨论