大家好,我是程序员二叉。
简介
在Redis + MySQL 主流架构中,缓存与数据库数据不一致是后端开发、面试高频重难点。很多线上故障、脏数据问题都源于双写流程设计不合理。
本文系统性梳理四种双写策略、两大主流执行顺序优劣、延时双删原理,以及金融级Canal订阅Binlog强一致性方案,全程标注重点、核心坑点,干货拉满,可直接收藏学习。欢迎点赞收藏关注。
一、为什么会出现双写不一致?
核心重点
数据库和缓存是两个独立存储组件,更新操作无法做到原子执行。
一旦两次操作顺序错乱、并发交织,就会出现:
- 数据库已更新,缓存还是旧数据
- 缓存更新完成,数据库未同步
最终产生脏数据,影响业务正常使用。
二、缓存+数据库 四种双写策略(全对比)
1. 先更新数据库 → 再更新缓存
强烈不推荐,线上禁用
执行流程:更新DB → 更新Redis
致命问题:
高并发场景下,后提交的数据库请求,反而先完成缓存更新,新数据被旧数据覆盖,永久数据不一致。
2. 先更新数据库 → 再删除缓存
业界主流通用方案(首选)
执行流程:更新DB → 删除Redis对应Key
核心思路:采用懒加载,查询时再回填最新数据。
优点
缺点(极端边界场景)
读+写并发交织会短暂出现脏数据:
该场景发生条件苛刻,正常业务流量下几乎不会触发。
3. 先删除缓存 → 再更新数据库
不推荐,高并发必出问题
执行流程:删除Redis → 更新DB
优点
流程直观,新手易理解
致命缺点
高并发读写场景极易产生永久脏数据:
最终结果:DB是新数据,缓存是旧数据,数据永久不一致。
4. 基于Binlog异步更新缓存
强一致性方案(金融/支付核心业务首选
执行流程:业务只操作DB → 中间件监听Binlog → 异步更新缓存
下文单独详解,适合零容忍脏数据场景。
三、延时双删策略(优化「先删缓存再更新DB」)
1. 适用场景
业务强制要求使用先删缓存流程,又要解决并发脏数据问题,采用延时双删做兜底。
2. 完整执行流程
3. 原理详解
核心重点
休眠时间需要大于「查询数据库 + 写入缓存」的最大耗时。
目的:把并发读请求回填到缓存的旧数据再次清除,保证缓存为空,下次查询加载最新数据。
4. 优缺点
优点
有效解决「先删缓存」带来的并发脏数据问题,架构改动小。
缺点
四、 强一致性终极方案:Canal 订阅 MySQL Binlog
1. 适用场景
金融、电商交易、支付、订单等不允许出现任何脏数据,对数据一致性要求极高的业务。
2. 核心原理
业务代码只操作数据库,完全不触碰缓存,依靠中间件实现缓存同步,做到解耦+强一致。
3. 整体架构&执行流程
4. 核心优势
5. 缺点
架构复杂度提升,需要维护 Canal、MQ 等中间件,运维成本更高。
五、 方案选型总结(线上落地指南)
优先选择:先更新数据库,再删除缓存
实现简单、性能最优,互联网绝大多数项目通用。
选择:延时双删策略
作为兜底优化方案,折中解决并发问题。
选择:Canal + Binlog + MQ 异步同步
工业级强一致方案,零脏数据风险。

