缓存和数据库的一致性,别停在 “延时双删”

图解数据库和Redis缓存的一致性(延时双删与延时后删的区别及重要性) 图解数据库和Redis缓存的一致性 问题来源 使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库: 读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题。 不管是先写MySQL数据库,再删除Redis缓存,再更新缓存;还是先删除缓存,再写库,再更新缓存。都有可能出现数据不一致的情况。举一个例子: 1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓 阅读详情

商品详情页是后端最典型的读写并发场景。一天几千万次请求,九成以上打在读上,价格、库存状态、促销标签全在 Redis 里躺着。写操作每天只占千分之几,却足以让缓存和数据库打架。

先说说延时双删(也有人叫延迟双删)是怎么回事。它是这样一套动作:

删除缓存 → 更新数据库 → 等待几百毫秒 → 再次删除缓存

第一删是为了让后续读请求不至于读到老值;第二删是清理等待窗口内被重新回填的旧数据。

这套方案本身没有大问题,最大误区是把它当成最终方案。真正上线后,故障远不止 “第二次删除失败” 这一种。


一、那些被忽略的空档

先看最朴素的执行顺序:先更新数据库、再删缓存。

读请求 A:

  1. T1:缓存未命中
  2. T2:查询数据库拿到旧值 100
  3. T3:把旧值写回缓存

写请求 B 在 A 读库、写缓存的间隙里,完成了数据库更新并删除缓存。此时缓存本就是空的,这次删除毫无作用。等 A 把旧值写入缓存,缓存与数据库数据永久不一致,且没有自动修复机制。

于是业界改成:先删缓存,再更新数据库。 只是把风险窗口从 “读回填” 挪到 “数据库事务未提交”。窗口变窄,但并未消失:如果读请求在第一次删缓存之后、数据库提交之前进入,依然会读到旧值并回填缓存。

真正闭环:CDC 订阅 binlog

用 Canal 订阅 MySQL 的 binlog,等数据库事务真正提交成功后,再触发缓存删除。

  • 触发逻辑从 “业务代码手动调用” 变成 “数据真实变更才执行”,天然保证顺序;
  • 解决正常业务路径下的数据不一致问题;
  • 短板:无法处理消费失败、消息积压、消费者重启丢失位点。

二、删除失败与缓存回血

Canal 消费失败、Redis 删除失败,只靠 “同步重试 3 次” 远远不够。标准落地是两层兜底方案:

1)MQ 异步重试(第一层保障)

  • 缓存删除请求投递到消息队列;
  • 消费失败采用指数退避重试;
  • 超过重试阈值,消息进入死信队列并触发告警;
  • 前提:删除操作必须幂等,删除不存在的 key 不报错,多次执行结果一致,重试不会产生副作用。

重点:重试绝对不能放在业务线程同步执行。同步重试会拉长接口 RT,一旦 Redis 抖动,直接阻塞下单核心链路。删除操作必须异步入队,业务线程只负责发消息。

2)定时增量对账(第二层兜底)

只抓取一段时间内发生变更的商品 ID,批量对比缓存与数据库数据,发现不一致就主动修正。 不用全表扫描,只核对变更数据集,对数据库压力可控。

旧值回血问题(并发读回填脏数据)

缓存被旧值覆盖,根源在读请求回填逻辑,单纯靠重试删缓存解决不了。两种治理方案:

  1. 版本号控制(治本) 缓存 value 带上版本号(更新时间戳也可),读请求回填前先比对版本;如果当前数据版本低于缓存已有版本,直接丢弃写入,慢半拍的旧数据永远覆盖不了新数据。
  2. 短 TTL + 对账兜底(保底) 给缓存设置几十秒过期时间,脏数据最多存活几十秒,等待定时任务自动修正。

通常两个方案一起使用。

衍生问题:主从同步延迟

写主库、读从库,binlog 同步存在几十~几百毫秒延迟。这段时间从库读到的依然是旧数据,回填缓存就会产生脏数据。

两种解法:

  • 强一致性场景(秒杀价格、库存):更新后的一小段时间,读请求强制路由主库;
  • 低成本方案:把缓存删除延迟时间拉长,覆盖主从同步耗时,预留足够时间余量。

三、删太多和删太频:高并发下的性能问题

一致性方案必然带来性能损耗,在高并发场景下会被成倍放大。

场景 1:批量更新(大量 key 集中删除)

运营一次性批量修改 5 万个 SKU 价格,循环删除 5 万个 Redis key,瞬间击穿缓存,大量请求直接穿透到数据库,缓存整体失效。

优化手段:

  1. 分批执行:ID 拆分,每批几百个,批次之间增加时间间隔;
  2. 避免直接删除:只把版本号 + 1,依靠 TTL 让旧缓存自然失效;
  3. 大键删除使用 UNLINK,不要用 DEL,防止阻塞 Redis 主线程。

场景 2:热点 Key 击穿

爆款商品缓存一旦被删除,上万并发请求同时击穿到数据库,直接把 DB 打满。

优化方案:

  1. 热点 Key 不设置自动过期,由后台定时任务主动刷新;删除时加分布式锁,只放行一个请求重建缓存,其余请求等待;
  2. 逻辑过期(最优方案):缓存里写入过期时间,读到过期数据时,先把旧值返回给用户,同时异步刷新缓存,用户完全无感知。

额外优化:多级缓存

读多写少场景增加本地缓存:Caffeine 一级本地缓存 + Redis 二级远程缓存,大幅减少跨网络调用。 代价:多实例部署下本地缓存很难做到强一致,依靠广播失效 + 1~2 秒短 TTL 兜底即可。


四、先明确业务需要哪种一致性

不是所有业务都要上一整套强一致方案,按需选型才是最优解。

  1. 强一致(核心交易数据) 价格、库存、优惠券状态,一旦出错直接造成资金损失。 方案:读请求强制走主库;缓存只做加速,不作为权威数据源;缓存删除失败直接阻塞或降级,宁可慢,不能错。
  2. 最终一致(普通商品信息) 商品标题、详情图、店铺公告,数据延迟几秒完全不影响用户体验。 方案:Canal 异步删缓存 + 定时对账兜底,成本与收益匹配。
  3. 允许误差(计数类数据) 浏览量、点赞数、曝光计数,写入量大,允许少量误差。 方案:先写缓存,异步刷入数据库,定期校准;没必要为这类数据搭建复杂的强一致架构。

选型标准:评估数据不一致的时长、误差范围,业务能否接受。把这个边界确认清楚,方案自然就定下来了。


五、落地代码的几条经验

  1. 所有缓存删除操作必须打印日志并埋点监控:删除失败次数、重试次数、死信队列堆积量,这三项指标比架构图更能反映链路健康度。
  2. 缓存 Key 命名要可以反向追溯数据表,方便定位脏数据,也便于对账任务按业务分片执行。
  3. 对账任务严禁全表扫描。采用增量时间窗比对,配合每日凌晨低峰期少量全量抽样校验。
  4. 数据库事务未提交前,绝对不能发送缓存删除消息。使用事务消息 / 本地消息表保证:事务提交成功才发消息。否则消息先到、数据库还没提交,删完缓存立刻被旧值回填。

最后总结

缓存一致性的难点,不在于选择延时双删还是 CDC,而在于把失效边界梳理清楚:

  • 什么场景会产生脏数据?
  • 脏数据最多存活多久?
  • 谁负责自动修复?
  • 修复失败会造成多大业务影响?

把这四个问题答完整,才算真正吃透这套方案。

延时双删只是业务流程里的临时补丁,不是架构级解决方案。真正的方案,藏在数据变更的全链路里:变更从哪里发出、经过哪些环节、失败如何兜底、多久能够自愈。链路理顺之后,不管是双删还是 CDC,都只是整个链路中的一环。

SpringBoot AOP + Redis 延时双删功能实战 如果我们没有第二次删除操作,此时有请求访问数据,有可能是访问的之前未做修改的Redis数据,删除操作执行后,Redis为空,有请求进来时,便会去访问数据库,此时数据库中的数据已是更新后的数据,保证了数据的一致性。注意:要知道经常修改的数据表不适合使用Redis,因为双删策略执行的结果是把Redis中保存的那条数据删除了,以后的查询就都会去查询数据库。在多线程并发情况下,假设有两个数据库修改请求,为保证数据库与redis的数据一致性,修改请求的实现中需要修改数据库后,级联修改Redis中的数据。 阅读详情

相关推荐

Redis延时双删详解

不禁要问:Tell me why?下面用来讲,越具体越直观。

qq_36428821的博客 1066

redis缓存为什么要延时双删

redis缓存为什么要延时双删

文盲青年的博客 2万+

基于51单片机的智能花盆灌溉系统设计与实现

本文详细介绍了基于51单片机的智能花盆灌溉系统设计与实现,通过DS18B20温度传感器、土壤湿度传感器和LCD1602显示屏等硬件模块,结合精确的算法控制,实现自动监测与灌溉。系统解决了传统灌溉依赖定时器、缺乏可视化界面的问题,适合上班族、园艺爱好者和植物园工作人员使用,有效提升植物养护效率。

honey的博客 1012

【Redis】所以延迟双删有啥用

延迟双删(Delay Double Delete)是一种在数据更新或删除时为了保证数据一致性而采取的策略。这种策略通常用于解决数据在缓存和数据库中不一致的问题。 具体来说,在某些场景下,我们需要先更新或删除数据库中的数据,然后再更新或删除缓存中的数据,以保证数据的一致性。但在某些情况下,由于网络延迟、服务器故障或其他原因,可能导致缓存中的数据更新或删除失败,从而导致数据库和缓存中的数据不一致。

陈宝子的博客 2万+

Win11 24H2家庭版共享打印机失败?别慌,一个批处理脚本搞定所有设置

本文提供了Win11 24H2家庭版共享打印机失败的解决方案,通过一个批处理脚本自动修复所有设置问题。脚本包含安装组策略组件、修改关键注册表项等操作,帮助用户快速恢复打印机共享功能,适用于普通家庭用户。

weixin_30632089的博客 417

Stata中介效应分析实战:从sgmediation安装到Sobel检验结果解读

本文提供了Stata中进行中介效应分析的完整实战指南,重点介绍了第三方命令sgmediation的安装、配置与使用。通过详细案例演示了如何运用Sobel检验分析变量间的间接效应,并深入解读检验结果,帮助研究者厘清自变量影响因变量的具体路径。文章还探讨了Sobel检验的原理、优缺点及结果报告规范,是进行实证研究的实用参考。

weixin_29197051的博客 628

缓存与数据库一致性——延迟双删

延迟双删(Delay Double Delete)是一种在数据更新或删除时为了保证数据一致性而采取的策略。这种策略通常用于解决数据在缓存和数据库中不一致的问题。

ksidgx的博客 7728

解锁SPWM电压利用率:三次谐波注入幅值的黄金分割点

本文深入探讨了SPWM电压利用率的提升方法,重点介绍了三次谐波注入技术及其黄金分割点(1/6比例)。通过数学推导和工程实践,揭示了如何通过特定幅值的三次谐波注入将电压利用率从86.6%提升至115%,与SVPWM相当。文章还提供了实验室调试流程和DSP实现代码,帮助工程师优化逆变器设计。

weixin_30729609的博客 915

图文讲解“延时双删”原因及必要性

Redis延时双删原因及必要性

yytree123的博客 1万+

【强化学习】11 —— Double DQN算法与Dueling DQN算法

可以看到由于数据点的分布,使得拟合出的价值函数无法与真实的价值函数吻合,甚至在部分区域产生了明显的偏差。Dueling DQN 是 DQN 另一种的改进算法,它在传统 DQN 的基础上只进行了微小的改动,但却能大幅提升 DQN 的表现。这样,即使其中一套神经网络的某个动作存在比较严重的过高估计问题,由于另一套神经网络的存在,这个动作最终使用的值不会存在很大的过高估计问题。.在同一个状态下,所有动作的优势值之和为 0,因为所有动作的动作价值的期望就是这个状态的状态价值。环境的状态包括倒立摆角度的正弦值。

sinat_52032317的博客 1万+

华为数通方向HCIP-DataCom H12-831题库(多选题:121-140)

华为数通HCIP H12-831多选题

didiplus 1290

缓存“延时双删”真的有必要吗?我觉得没有

第一次清空缓存后,更新数据库前的这段时间内,其他事务查询了数据库的数据,第二次清空缓存后,刚才查询数据库 的那个线程又更新了缓存,此时又会将旧数据更新到缓存

程序员资料站 6715

开心消消乐

1)当点击一个1时,该1变被反转为0,同时相邻的上、下、左、右,以及左上、左下、右上、右下8个方向的1(如果存在1)均会自动反转为0;2)进一步地,一个位置上的1被反转为0时,与其相邻的8个方向的1(如果存在1)均会自动反转为0;上述样例中,四个角上的1均在中间的1的相邻8个方向上,因此只需要点击一次即可。给定一个N行M列的二维矩阵,矩阵中每个位置的数字取值为0或1。在上述4 * 4的矩阵中,只需要点击2次,即可将所有的1进行消除。接下来N行表示矩阵的初始值,每行均为M个数,取值范围[0,1]

面试高手的博客 2725

【SpringBoot AOP Redis实现延时双删功能实战】

一、业务场景 在多线程并发情况下,假设有两个数据库修改请求,为保证数据库与redis的数据一致性, 修改请求的实现中需要修改数据库后,级联修改redis中的数据。 请求一:A修改数据库数据 B修改redis数据 请求二:C修改数据库数据 D修改redis数据 并发情况下就会存在A ---> C ---> D ---> B的情况 (一定要理解线程并发执行多组原子操作执行顺序是可能存在交叉现象的) ## 1、此时存在的问题 A修改数据库的数据最终保存到了redis中,C在A之后也修改了数据库数据。 此

jike11231的博客 5756

8.9华为OD机试真题 新系统 - 灯带颜色变换 (Java/Py/C/C++/Js/Go)

8.9华为OD机试真题 新系统 - 灯带颜色变换 (Java/Py/C/C++/Js/Go)

算法大师! 663

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

缓存为什么要延时双删?

如何保证数据库数据与缓存的一致性?为什么最终选择延时双删策略

珈凝的博客 5096

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Redis延时双删

双删依然存在旧缓存的情况,延时是确保 修改数据库->清空缓存前,其他事务的更改缓存操作已经执行完。

咖啡有点苦的博客 4433

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

redis数据一致性之延时双删详解

在使用redis时,需要保持redis和数据库数据的一致性,最流行的解决方案之一就是延时双删策略,今天我们就来详细刨析一下 注意:要知道经常修改的数据表不适合使用redis,因为双删策略执行的结果是把redis中保存的那条数据删除了,以后的查询就都会去查询数据库。所以redis使用的是读远远大于改的数据缓存。 1,首先要理解在并发环境下redis数据一致性的问题所在 在多线程并发情况下,假设有两个数据库修改请求,为保证数据库与redis的数据一致性, 修改请求的实现中需要修改数据库后,级联修改redis中的

zzz的博客 2万+

Java并发编程--38-缓存与数据库双写一致性:先删还是先更?延时双删够用吗?

本文探讨了缓存与数据库双写一致性问题,分析了常见方案的优缺点。核心观点包括: Cache-Aside模式是基础方案,通过先更新数据库再删除缓存来保证一致性,但存在短暂不一致窗口 先删缓存再更新数据库的方案会导致严重脏数据问题 延时双删可以缓解但无法彻底解决不一致问题 生产环境推荐使用Canal监听MySQL binlog异步更新缓存的最终一致性方案 文章对比了不同方案的实现原理和适用场景,指出强一致性需要分布式事务,而大多数业务场景可采用最终一致性。最后提供了面试标准答案和选型指南,建议核心数据使用Cana

weisian的博客 3699

删缓存,数据库更新谁先执行,及延时双删

先操作哪个,主要问题不是其中一个执行失败的问题 先删除缓存,再更新数据库:存在主要问题不是更新数据库失败,导致读到老数据, 是并发情况下删除缓存后,立刻读库,此时库数据还没更新,读到了老数据,又写入了缓存,导致以后所有人读到都是缓存中错误数据 先更新数据库,再删除缓存:存在主要问题是,更新数据库后,还没删除缓存,导致部分人读到了缓存中老数据,当缓存删除后,就可以从数据库读取正确数据,缓存也就正确,以后大部分人读到正确数据。 ...

C18298182575的博客 1924

延时双删 vs 双写一致:缓存一致性终极对决

延时双删是轻量、高效、易实现的最终一致性方案,适配 90% 的读多写少、允许短暂不一致的业务,是中小型项目的首选;双写一致是复杂、高性能读、强一致性的方案,适配 10% 的写多读少、对一致性要求极高的核心业务,需处理并发和失败重试;二者并非互斥,可根据业务 key 的重要性做混合选型,同时搭配缓存过期时间、binlog 同步实现多重兜底,最大化保证数据一致性。

2502_92082922的博客 790

【Redis】延时双删策略

摘要:延时双删策略是一种解决数据库与缓存数据一致性问题的折中方案。其核心步骤为:先删除缓存,再更新数据库,最后延时后二次删除缓存。该策略通过两次删除和延时等待降低脏数据残留概率,适用于对一致性要求较高但无法引入复杂中间件的场景。虽然实现简单,但存在吞吐量下降和延时时间难以评估的缺点,通常需结合异步操作和缓存过期机制来优化。这是一种以性能换取一致性的实用工程实践。

m0_73609995的博客 1238

如何保证缓存与数据库的一致性?

目录 先删缓存,再更新数据库 解决方案 延时双删 先更新数据库,再删除缓存 解决方案 消息队列 进阶版消息队列 其他解决方案 设置缓存过期时间 为什么是删除,而不是更新缓存? 总结 对于缓存和数据库的操作,主要有以下两种方式。 先删缓存,再更新数据库 先删除缓存,数据库还没有更新成功,此时如果读取缓存,缓存不存在,去数据库中读取到的是旧值,缓存不一致发生。 解决方案 延时双删 延时双删的方案的思路是,为了避免更新数据库的时候,其他线程从缓存中读取不到数据,就在更新完数

javaTalk 4417

延时双删两种实现对比分析

延时双删(Delayed Double Deletion)是一种在分布式系统或缓存一致性处理中使用的技术,目的是确保缓存与数据库之间的数据一致性。它主要用于处理在高并发情况下,缓存和数据库可能出现的数据不一致问题,本文简单分析了两种常用方式优劣情况。

CoderJia的学习之路 1687

深入剖析缓存一致性问题:延时双删的利弊与替代方案

在当今的分布式系统架构中,缓存凭借其快速的数据读取能力,成为提升系统性能和响应速度的关键组件。然而,缓存的引入也带来了缓存一致性问题,这一问题成为开发者在系统设计与维护中必须攻克的难关。缓存一致性问题聚焦于数据更新时,如何确保数据库和缓存中的数据始终保持同步,一旦处理不当,数据不一致的情况就会出现,进而引发各类难以排查和修复的系统故障。在实际的系统运行中,缓存一致性问题主要集中在数据更新操作阶段。当数据库中的数据发生变动,缓存中的对应数据也需要及时更新,以保证数据的一致性。常见的读写场景如下:读操作流程:系

听得到微笑的博客 2063
上一篇: Redis 为什么快?把“存内存“这句话拆开看
下一篇: AI PC 分水岭:2026 过半 PC 搭载本地 AI,端云协同才是核心
Codiggerworld
博客等级 码龄3年 29粉丝 101原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值