在上一篇文章中我们构建了“Nginx本地缓存 → Redis → Tomcat”的三级缓存架构性能直接起飞。但随之而来的是一个经典难题缓存一致性。当后台管理员修改了商品价格或库存后如何确保Nginx和Redis里的旧数据能被及时清理如果处理不好用户看到的将是“过期”的商品信息甚至引发超卖等严重事故。今天我们就来深入探讨四种主流的缓存同步策略看看哪种最适合你的业务场景。策略一设置有效期被动过期这是最简单、最暴力的方案也是我们目前在OpenResty本地缓存中采用的方式。核心原理给缓存设置一个“保质期”TTL。比如商品信息设置30分钟过期。在这30分钟内即使数据库修改了数据缓存依然返回旧值直到它自然死亡下次查询才会重新加载。优点实现极其简单无需额外代码性能最好。缺点时效性差存在“脏读”窗口期。适用场景对实时性要求不高的数据如商品描述、规格参数、商品图片等。策略二同步双写强一致性如果你要求数据必须实时一致最直接的想法就是在更新数据库的同时同步更新缓存。核心原理将“写数据库”和“写缓存”放在同一个事务中。开启事务。更新数据库Update DB。更新/删除缓存Update/Del Cache。提交事务。优点强一致性数据更新立即可见。缺点高耦合业务代码不仅要管数据库还要管缓存逻辑。如果以后引入了Redis、本地缓存、ES等多个存储业务代码会变得臃肿不堪。性能损耗写操作必须等待缓存更新完成增加了响应时间。适用场景对一致性要求极高的核心数据如金融账户余额、秒杀库存扣减。策略三异步通知MQ解耦为了解决同步双写的耦合问题我们可以引入消息队列MQ进行解耦。核心原理业务服务更新数据库后向MQ发送一条“数据变更消息”。缓存服务或OpenResty订阅该消息。收到消息后异步执行缓存删除或更新操作。优点低耦合业务代码只需发消息不用关心谁在消费一条消息可以被多个消费者如Redis、本地缓存、搜索引擎同时处理。缺点存在毫秒级的延迟属于“最终一致性”。适用场景允许多服务同步、对实时性要求不是毫秒级的场景。策略四基于Canal的异步通知零侵入这是目前大厂最流行的方案它连MQ的消息发送代码都不需要写做到了真正的“零侵入”。核心原理利用MySQL的主从复制协议。Canal伪装成MySQL的从库监听MySQL的Binlog二进制日志。当数据库发生增删改操作时Binlog会产生日志。Canal捕获这些日志解析出数据变更。Canal将变更推送给缓存服务触发缓存更新。优点零侵入业务代码完全不需要改动只管写数据库。高可靠基于数据库日志不会丢失。高性能比MQ方案更直接延迟更低。缺点需要额外部署Canal组件架构复杂度增加。适用场景几乎所有对一致性有要求、且希望业务纯净的场景。总结与选型建议没有最好的策略只有最适合的策略。在实际的多级缓存架构中我们通常是组合使用商品基本信息如标题、描述使用“设置有效期”。因为这类数据很少变动容忍短暂不一致。商品核心数据如价格、库存使用“Canal异步通知”或“同步双写”。确保用户看到的价格和库存是准确的。策略对比表策略时效性耦合度实现难度适用场景设置有效期差分钟级延迟低简单商品描述、规格同步双写强实时高中等秒杀库存、金融数据MQ异步通知中毫秒级延迟中较复杂多服务数据同步Canal监听优毫秒级延迟无零侵入复杂核心业务数据同步知识点核心总结知识点核心内容考试重点/易混淆点难度系数多级缓存架构通过多级缓存提高商品查询性能但引入一致性问题缓存与数据库不一致的场景分析缓存同步策略有效期控制被动同步设置缓存过期时间到期后自动删除时效性差适用于更新频率低的数据如商品描述、规格缓存同步策略同步双写数据库与缓存写操作绑定为事务保证强一致性代码侵入性强适合高一致性要求的场景如价格、库存缓存同步策略异步通知通过事件通知如MQ触发缓存更新解耦业务逻辑时效性中等适合多服务同步场景Canal异步方案监听MySQL binlog实现零侵入缓存更新比MQ方案时效性更高无代码耦合策略对比维度时效性同步双写 Canal MQ 有效期; 耦合度同步双写 MQ Canal零侵入业务场景选择依据更新频率、一致性要求、系统复杂度