聊聊数据异构与多级缓存同步方案
在大型内容创作平台中,业务形态往往非常多样,涵盖文章、单品推荐、搭配、店铺上新、秒杀、直播预告及优惠券等。这些内容通常需要投稿到不同频道,而频道的曝光前提是内容通过质量审核(一审)及频道侧二审。部分强时效性内容如直播预告或优惠券可免审外露,其余则需经过 CMS 后台的一至两道审核流程,或在质检抽查中复活。
这类内容体裁普遍呈现'读多写少'的特征,因此高度依赖缓存。然而,业务逻辑中频繁涉及直接写入或更新缓存的场景,例如无需审核的内容发布、审核状态变更、标签编辑、定时上下线等。这就需要一个组件化的服务来确保数据同步。如果由你来设计一套缓存或多级缓存同步方案,该如何处理?核心在于实现数据的异地异构存储,即将整合后的多表数据构建成一条记录并异步同步。
方案一:双写模式
最直观的做法是在业务代码中对数据库操作时同步更新缓存。但这种硬编码方式侵入性较强,首要挑战是事务一致性——如何保证数据库与缓存要么同时成功,要么同时失败。一旦引入分布式事务,性能损耗会非常明显。
另一种常见变体是'先删缓存后更库',利用查询操作回填缓存。这种方案最大的隐患在于热点数据:若恰好删除了热点缓存,瞬间涌入的大量请求将直接击穿数据库。此外,极端情况下缓存节点不可用、网络延迟增加或程序重启未能及时同步,都会导致服务性能下降及数据不一致。
方案二:消息队列异步双写
为了解决同步阻塞问题,可以改用 MQ 进行异步双写。业务逻辑完成后发送事件通知,由不同应用消费 MQ 分别写入数据库和缓存,其中写缓存的应用再反查其他表。相比同步双写,此方案性能显著提升,且可利用 MQ 重试机制保障数据不丢失。
但缺点同样存在:硬编码耦合未完全消除,且引入了时延。由于部分 MQ 消息需串行处理,或因网络波动导致消费不及时,用户可能无法立即看到操作结果。
方案三:定时任务轮询
在数据表中增加时间戳字段,任何更新均触发该字段变化。定时器定期扫描表,提取时间段内变化的数据逐条同步至缓存。这种方式对数据库造成较大的轮询压力,生产环境通常不建议采用。
方案四:基于 MySQL Binlog 的异构
有没有更优雅的解法?答案是利用 MySQL 的 binlog 日志。
MySQL binlog 主要用于主从复制、数据恢复及增量备份,具备高可靠性与低延迟特性。我们可以构建中间件系统,伪装成 Master 的 Slave,读取 binlog 中的数据变更,将其二进制格式化为 MQ 消息传输,下游程序消费后同步缓存。
该方案实现了业务代码与缓存逻辑的彻底解耦。当然,缺点是需要维护额外的中间件系统。若无此条件,前述的 MQ 异步双写仍是较优选择。
数据异构技术不仅适用于多级缓存同步,还可解决分库分表后的数据迁移等复杂问题,后者涉及更多数据校验逻辑,此处不再展开。


