欢迎光临
我们一直在努力

【Redis】 吃透Redis缓存与数据库双写一致性|4大策略+延时双删+Canal强一致方案(面试必刷)

大家好,我是程序员二叉。


简介

在Redis + MySQL 主流架构中,缓存与数据库数据不一致是后端开发、面试高频重难点。很多线上故障、脏数据问题都源于双写流程设计不合理。

本文系统性梳理四种双写策略、两大主流执行顺序优劣、延时双删原理,以及金融级Canal订阅Binlog强一致性方案,全程标注重点、核心坑点,干货拉满,可直接收藏学习。欢迎点赞收藏关注。


一、为什么会出现双写不一致?

核心重点
数据库和缓存是两个独立存储组件,更新操作无法做到原子执行。
一旦两次操作顺序错乱、并发交织,就会出现:

  • 数据库已更新,缓存还是旧数据
  • 缓存更新完成,数据库未同步
    最终产生脏数据,影响业务正常使用。

二、缓存+数据库 四种双写策略(全对比)

1. 先更新数据库 → 再更新缓存

强烈不推荐,线上禁用
执行流程:更新DB → 更新Redis
致命问题:
高并发场景下,后提交的数据库请求,反而先完成缓存更新,新数据被旧数据覆盖,永久数据不一致。

2. 先更新数据库 → 再删除缓存

业界主流通用方案(首选)
执行流程:更新DB → 删除Redis对应Key
核心思路:采用懒加载,查询时再回填最新数据。

优点
  • 规避缓存互相覆盖问题,逻辑简单、性能高
  • 冷数据自动淘汰,节省Redis内存
  • 并发冲突概率极低,绝大多数业务场景完全够用
  • 缺点(极端边界场景)

    读+写并发交织会短暂出现脏数据:

  • 读请求A:缓存未命中,查询MySQL拿到旧数据
  • 写请求B:更新MySQL,并删除缓存
  • 读请求A:把拿到的旧数据写入缓存
  • 该场景发生条件苛刻,正常业务流量下几乎不会触发。

    3. 先删除缓存 → 再更新数据库

    不推荐,高并发必出问题
    执行流程:删除Redis → 更新DB

    优点

    流程直观,新手易理解

    致命缺点

    高并发读写场景极易产生永久脏数据:

  • 写请求A:删除缓存,开始更新数据库
  • 读请求B:缓存为空,查询MySQL拿到旧数据,写入缓存
  • 写请求A:数据库更新完成
  • 最终结果:DB是新数据,缓存是旧数据,数据永久不一致。

    4. 基于Binlog异步更新缓存

    强一致性方案(金融/支付核心业务首选
    执行流程:业务只操作DB → 中间件监听Binlog → 异步更新缓存
    下文单独详解,适合零容忍脏数据场景。


    三、延时双删策略(优化「先删缓存再更新DB」)

    1. 适用场景

    业务强制要求使用先删缓存流程,又要解决并发脏数据问题,采用延时双删做兜底。

    2. 完整执行流程

  • 第一次删除缓存
  • 更新数据库
  • 线程休眠一段时间(延迟等待)
  • 第二次删除缓存
  • 3. 原理详解

    核心重点
    休眠时间需要大于「查询数据库 + 写入缓存」的最大耗时。
    目的:把并发读请求回填到缓存的旧数据再次清除,保证缓存为空,下次查询加载最新数据。

    4. 优缺点

    优点

    有效解决「先删缓存」带来的并发脏数据问题,架构改动小。

    缺点
  • 线程休眠阻塞请求,接口性能下降
  • 延迟时间依赖经验配置,难以精准适配所有网络环境
  • 仅保证最终一致性,无法做到实时强一致

  • 四、 强一致性终极方案:Canal 订阅 MySQL Binlog

    1. 适用场景

    金融、电商交易、支付、订单等不允许出现任何脏数据,对数据一致性要求极高的业务。

    2. 核心原理

    业务代码只操作数据库,完全不触碰缓存,依靠中间件实现缓存同步,做到解耦+强一致。

    3. 整体架构&执行流程

  • 业务请求执行 增/改/删,更新MySQL数据库
  • MySQL 数据变更,自动记录 Binlog 二进制日志
  • Canal 伪装成MySQL从节点,实时监听、拉取Binlog日志
  • Canal 解析日志,提取表名、主键、变更后数据
  • 将数据变更消息投递到 RocketMQ/Kafka 消息队列
  • 消费服务监听MQ,消费消息并更新/删除Redis缓存
  • 4. 核心优势

  • 数据强一致:数据库为唯一数据源,缓存被动同步,从根源避免双写错乱
  • 业务零侵入:原有代码无需改动,同步逻辑完全独立
  • 高可用&削峰:依靠MQ异步解耦,不影响主业务吞吐量
  • 支持重试、故障恢复,稳定性远高于代码硬编码双写
  • 5. 缺点

    架构复杂度提升,需要维护 Canal、MQ 等中间件,运维成本更高。


    五、 方案选型总结(线上落地指南)

  • 普通业务、允许短暂不一致
    优先选择:先更新数据库,再删除缓存
  • 实现简单、性能最优,互联网绝大多数项目通用。

  • 历史架构固定,必须先删缓存
    选择:延时双删策略
  • 作为兜底优化方案,折中解决并发问题。

  • 核心交易、金融、支付等强一致场景
    选择:Canal + Binlog + MQ 异步同步
  • 工业级强一致方案,零脏数据风险。


    六、总结(面试速记 精简背诵版)

  • 先更库再更缓存:并发覆盖,直接淘汰
  • 先更库再删缓存:主流方案,冲突概率极低
  • 先删缓存再更库:高并发必脏数据,慎用
  • 延时双删:删缓存 → 更库 → 延时 → 再删缓存,兜底旧数据
  • Canal订阅Binlog:强一致终极方案,监听数据库日志异步更新缓存
  • 赞(0)
    未经允许不得转载:171主机测评 » 【Redis】 吃透Redis缓存与数据库双写一致性|4大策略+延时双删+Canal强一致方案(面试必刷)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址