Redis|延迟双删策略的优点和缺点是什么?

news2024/10/23 15:24:30

延迟双删策略是什么?

延迟双删策略是一种保证缓存与数据库数据一致性的方法,特别适用于高并发场景下的缓存更新。其核心思想是:在更新数据库时,不仅删除一次缓存,还在短时间后再进行一次延迟删除,以避免并发问题导致的数据不一致。

延迟双删策略的步骤

  1. 第一次删除缓存:在更新数据库之前,先删除对应的缓存,确保缓存中不会存在旧数据。
  2. 更新数据库:执行数据库更新操作。
  3. 延迟一段时间后,再次删除缓存:为了防止在数据库更新后立即有并发请求读到了旧缓存数据,延迟一定时间(比如 1 秒)后,再次删除缓存,确保缓存中不存在陈旧的数据。

为什么需要延迟再删一次缓存?

在高并发的场景下,延迟双删策略可以有效避免以下两种常见的问题:

  1. 更新数据库后立即有请求查询:当某个线程刚更新完数据库,在其还未重新更新缓存前,有其他线程同时查询到了旧缓存数据。这种情况会导致数据库中的新数据还没被缓存,查询到的却是旧数据。
  2. 脏数据回填缓存:由于并发请求的存在,数据库更新后有可能缓存还没被删除或者重建,导致旧缓存被重新写入。

延迟双删策略的优点

  1. 提高数据一致性:通过延迟删除可以减少缓存中的陈旧数据,避免因并发请求导致的缓存数据与数据库数据不一致的问题。
  2. 减少缓存更新压力:相比于每次数据库更新都立即更新缓存,延迟双删避免了频繁的缓存更新请求,降低了缓存服务器的压力。
  3. 简单易实现:不需要对现有的缓存系统做太大的修改,只需在更新逻辑中加入两次删除操作,成本较低。

延迟双删策略的缺点

  1. 延迟时间的难以确定:延迟多久再删除缓存是一个难点。如果延迟时间太短,可能仍然会出现并发问题;如果延迟时间太长,则可能增加缓存中的陈旧数据存在的时间,影响数据一致性。
  2. 并发高时可能出现不一致:即使有延迟双删,极端高并发场景下(如延迟期间有大量请求访问),仍然可能出现数据不一致的情况。比如在延迟时间内,有大量读请求仍然会命中旧缓存。
  3. 多次缓存删除带来额外开销:延迟删除缓存意味着每次数据库更新后都要进行两次缓存删除操作,虽然可以保证数据一致性,但也可能带来额外的性能开销,特别是在高并发场景下,缓存的删除和重建会增加负载。

延迟双删策略适用场景

延迟双删策略适合于那些需要在高并发环境下保证缓存与数据库一致性的场景,特别是在更新操作频繁的系统中,比如电商、社交平台等需要对大量缓存数据进行频繁更新的应用场景。

示例

假设我们有一个电商系统,当用户下单时,库存数据需要更新。延迟双删的实现大致如下:

// 更新库存的伪代码
public void updateInventory(String productId, int newInventory) {
    // 第一次删除缓存
    cache.delete(productId);
    
    // 更新数据库中的库存信息
    database.updateInventory(productId, newInventory);
    
    // 延迟一段时间再删除缓存
    try {
        Thread.sleep(1000);  // 延迟1秒
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    // 再次删除缓存,确保数据一致性
    cache.delete(productId);
}

基础总结一下但是任然有问题:

延迟双删策略通过在数据库更新前和更新后延迟一段时间再次删除缓存,有效避免了在并发情况下缓存和数据库数据不一致的问题。虽然它能提高一致性,但需要合理设计延迟时间,并且在极高并发的场景下仍需考虑其他优化策略。

延迟双删策略无法完全做到强一致性!

延迟双删策略虽然能在一定程度上提高缓存与数据库的一致性,但它确实无法做到完全一致性,特别是在极高并发的情况下。下面是对这一点的详细分析:

为什么延迟双删策略不能做到彻底的一致性?

  1. 延迟时间难以完美把控

    • 延迟时间的设定是策略的核心,但它往往很难确定。设定的时间过短,可能无法覆盖到并发操作的峰值,从而导致旧缓存数据被读取。设定时间过长,则会影响系统性能和实时性。对于不同业务场景和流量模式,理想的延迟时间往往是动态变化的,这使得延迟双删的应用更具挑战性。
  2. 高并发场景下的并发写入问题

    • 在极高并发的场景下,即使使用延迟双删策略,仍可能出现多个线程同时操作缓存和数据库的情况。举个例子:
      • 线程 A 在删除缓存后,开始更新数据库;
      • 线程 B 在 A 更新数据库之前,查询到了缓存并回填了旧缓存数据;
      • 线程 A 的延迟删除动作也无法及时清理掉线程 B 填充的旧缓存。 这种情况下,会导致缓存中的数据仍然是旧的,从而发生不一致。
  3. 脏读问题

    • 在延迟删除的这段时间内,如果有并发的读取请求,可能会读到数据库更新后的旧缓存这在某些实时性要求高的应用中是不可接受的,比如金融系统或订单处理系统,必须保证读到的数据是最新的。
  4. 网络延迟和异常情况

    • 网络延迟、系统抖动等不确定因素也会影响延迟双删的效果。在分布式系统中,延迟双删依赖于多个系统的协作(如缓存、数据库、应用服务),如果某个环节出现异常,如缓存删除失败、网络延迟较大等,都可能导致数据不一致。

一致性问题的进一步讨论

严格来说,延迟双删策略提供的一致性保证是最终一致性,即在一段时间内,缓存和数据库的数据可能会出现不一致的情况,但在系统恢复到稳定状态时,缓存和数据库的数据最终会一致。

  • 强一致性(Strict Consistency)是指系统中每次读操作都能够获得最近的写操作的结果,要求每次数据读取都是最新的。这种一致性在延迟双删策略中是无法保证的。
  • 最终一致性(Eventual Consistency)则意味着经过一段时间后,系统的数据会变得一致,但在某些瞬间,数据可能不一致。延迟双删策略通常保证的是这一类一致性。

替代或补充的优化策略

对于高并发场景或者对一致性要求特别严格的系统,延迟双删策略可能不够,因此需要引入其他优化策略:

  1. 分布式锁

    • 在缓存更新时使用分布式锁(如 Redis 的 SETNX 加锁机制)确保只有一个线程能够更新缓存和数据库,避免并发写操作导致的缓存与数据库不一致。
  2. 消息队列

    • 使用消息队列进行缓存更新操作,将数据库更新后的缓存操作通过消息队列异步处理,从而保证顺序性和一致性。
  3. 强制缓存更新

    • 对于实时性要求较高的系统,可以强制要求在每次读写操作时更新缓存,保证缓存和数据库的数据是一致的,代价是性能损失更大。
  4. 写通过策略(Write-through Cache)

    • 直接在写入数据库时同步更新缓存,这样保证写入数据库的数据也一定进入缓存中,避免了缓存中存在旧数据的问题,但这增加了写操作的延迟。
  5. 读写分离

    • 可以通过数据库主从架构实现读写分离,将读取操作主要从缓存或者从库执行,减少对主库的压力,同时让主库专注于写操作并及时更新缓存。

强一致性的总结:

延迟双删策略虽然能在大部分场景下解决缓存与数据库不一致的问题,但它并不能保证强一致性,尤其是在高并发场景下或对一致性要求较高的系统中。其一致性保证更多的是最终一致性。如果业务系统对一致性要求较高,建议引入分布式锁、消息队列等其他优化策略来进一步提升一致性。

问题是为啥要延迟1s呢?不延迟可以吗?

延迟双删策略的核心目的是避免并发情况下缓存和数据库之间的短暂不一致问题。虽然延迟并不能阻止线程 B 并发操作,但它可以帮助我们在一个较短的时间窗口内修正数据的不一致性。我们来详细拆解一下这个问题:

问题核心:延迟 1 秒的目的

延迟的 1 秒钟确实是为了让数据库的更新有足够的时间被完全写入并提交,从而避免因为数据库更新延迟而导致的“脏数据”问题。具体来说,延迟 1 秒的主要目的是:

  1. 避免线程 A 更新数据库后立即读取脏数据:如果线程 A 在删除缓存和更新数据库后,马上读取数据库,可能会因为数据库还没有完全更新而读到旧数据。此时,如果缓存再次填充旧数据,会导致缓存不一致。延迟 1 秒的目的就是为了给数据库的更新操作留出足够的时间,让数据更新在数据库中被真正写入完成。

  2. 缓解线程 B 的并发读取问题:虽然延迟无法直接阻止线程 B 的并发操作,但如果线程 B 恰好在数据库还未更新完成时读取了旧数据并将其重新写入缓存,延迟后的第二次删除操作可以确保最终缓存中不会保留这些旧数据。因此,延迟 1 秒相当于一个最终修正手段,确保在并发场景下,旧数据不再保留太长时间。

并发情况下脏数据的问题

如果没有延迟,存在以下风险:

  • 线程 A 更新数据库时可能存在延迟:数据库操作通常是有耗时的,尤其是在高并发场景下。如果线程 A 在数据库更新后立即读取缓存,可能读到的还是旧数据。如果没有延迟,线程 A 可能会直接填充缓存为旧数据。

  • 线程 B 并发读取旧数据:在缓存删除和数据库更新之间的时间窗口内,线程 B 可能会读取旧的数据库数据,并将其重新写入缓存。如果没有延迟进行第二次缓存删除,旧数据将会长期存在于缓存中,导致缓存与数据库之间的数据不一致。

延迟并不是给线程 B 留的时间,而是给数据库写入时间

所以,延迟 1 秒的核心并不是为了让线程 B 等待,而是为了给数据库足够的时间完成更新,并确保缓存中不会保留因为并发读取而填充的旧数据。线程 A 的延迟删除缓存实际上是为了确保即便有线程 B 并发写入了旧数据,最终这些旧数据也会被删除,从而达到数据的一致性。

脏数据与缓存更新关系

如果线程 A 不进行延迟删除,那么在高并发的情况下:

  • 数据库更新的速度可能跟不上线程 A 的缓存操作速度,导致线程 A 或其他线程读取到未更新的数据(脏数据)。
  • 当并发请求(线程 B)读取旧数据时,这些旧数据会被重新写入缓存,导致缓存的数据和数据库中的数据不同步。

通过延迟删除缓存,可以确保线程 A 在更新数据库后,数据库中的数据有足够的时间更新完成,避免脏数据进入缓存。并且,即便有其他线程在缓存删除后的短时间内写入旧数据,延迟的第二次删除操作也能及时清除这些旧数据。

延迟1 秒的总结

延迟 1 秒的目的是为了给数据库更新操作预留时间,确保数据库在并发场景下能正确地完成更新,防止线程 A 或线程 B 在数据库还没更新完毕的情况下读取到旧数据。延迟删除缓存不是直接解决并发问题的手段,而是通过最终一致性的方式来确保缓存中不会长时间保留旧数据,减少缓存与数据库不一致的时间窗口。

如果并发场景特别复杂或者延迟时间难以估计,还可以引入其他手段(如分布式锁)来更加精细地控制缓存和数据库的同步问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.深入理解MySQL索引底层数据结构与算法

文章目录 索引的概念数据结构二叉树红黑树B-B两者的区别 Hash 引擎数据所在位置对应关系MyISAMInnoDB 索引主键聚集索引非聚集索引联合索引 如有写的不对的请指正。 索引的概念 索引是帮助MySQL高效获取数据的排好序的数据结构 数据结构 网址: https://www.cs.us…

Kafka-设计思想-2

一、消息传递语义 现在我们对生产者和消费者的工作方式有了一些了解,让我们讨论一下Kafka在生产者和消费者之间提供的语义保证。 1、最多发送一次:会造成数据丢失 2、至少发送一次:会造成数据重复消费 3、只发送一次:我们想要的效…

MDB收款适配器MDBPOS

LETPOS精简版MDBPOS(直接连接MDB协议的刷卡器,按照设定价格收款,输出脉冲) 通过串口设定价格,脉冲宽度。 有人刷卡,扣款成功,输出脉冲,使用简单 适合把MDB协议的刷卡器连接到脉冲投…

【算法】归并排序概念及例题运用

📢博客主页:https://blog.csdn.net/2301_779549673 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📢本文由 JohnKi 原创,首发于 CSDN🙉 📢未来很长&#…

小程序视频SDK解决方案,提供个性化开发和特效定制设计

美摄科技作为视频处理技术的领航者,深知在这一变革中,每一个细微的创新都能激发无限可能。因此,我们精心打造了一套小程序视频SDK解决方案,旨在满足不同行业、不同规模客户的多元化需求,携手共创视频内容的璀璨未来。 …

这几次比赛题解

因为考虑到再看&#xff0c;所以将所有题目都做成了pdf格式 梦熊十三连测 T1 这道题其实什么也不用想&#xff0c;就按照题目给的意思来打代码就行&#xff0c;这就有40分可以拿。懒人做法 #include<bits/stdc.h> using namespace std; typedef long long ll; ll read…

中航资本:股票显示缺口什么意思啊?股票有缺口一定会补吗?

股票显现缺口什么意思啊&#xff1f; 股票显现缺口是指股票在运行进程中&#xff0c;忽然上涨或许下跌使股价远离上一个交易日收盘价的状况&#xff0c;也便是股票当天的开盘价格和股票前一个交易日的收盘价格违背崎岖很大。在K线图中&#xff0c;缺口表现为股价在持续动摇中有…

MT-Pref数据集:包含18种语言的18k实例,涵盖多个领域。实验表明它能有效提升Tower模型在WMT23和FLORES基准测试中的翻译质量。

2024-10-10&#xff0c;由电信研究所、里斯本大学等联合创建MT-Pref数据集&#xff0c;它包含18种语言方向的18k实例&#xff0c;覆盖了2022年后的多个领域文本。通过在WMT23和FLORES基准测试上的实验&#xff0c;我们展示了使用MT-Pref数据集对Tower模型进行对齐可以显著提高翻…

React实现购物车功能

今日学习React的useReducer&#xff0c;实现了一个购物车功能 文章目录 目录 效果展示 逻辑代码 CSS代码 效果展示 逻辑代码 import {useReducer} from "react"; import ./index.css; import { message} from antd;export function ShoppingCount(){// 初始化购…

钡铼技术边缘计算2DIN2DO工业无线路由器R40A

R40A不仅具备了传统工业无线路由器的基本功能&#xff0c;如4G网络连接、稳定的数据传输等&#xff0c;还创新性地整合了可编程逻辑控制器&#xff08;PLC&#xff09;功能、多种工业协议转换能力以及数据采集终端的功能。 强大的边缘计算能力 随着物联网技术的发展&#xff…

STM32_实验5_中断实验

通过外部中断来检测四个按键按下的状态&#xff1a; WK_UP 控制蜂鸣器响和停 KEY0 控制 LED_R 互斥点亮 KEY1 控制 LED_G 互斥点亮 KEY2 控制 LED_B 互斥点亮。 中断的基本概念&#xff1a; 中断请求&#xff08;IRQ&#xff09;&#xff1a; 当发生某个特定事件&#xff08;例…

如何通过谷歌外推占据搜索引擎首页?

外贸企业在推广过程中&#xff0c;如何在谷歌搜索引擎中占据有利位置&#xff0c;获取更多曝光&#xff0c;GLB谷歌霸屏服务就可以派上用场。它通过高效的品牌外推策略&#xff0c;可以让你的企业信息在谷歌中实现“霸屏”效果&#xff0c;特别是长尾关键词的全面覆盖 很多企业…

如何实现安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯

在工业自动化中&#xff0c;实现不同品牌、不同型号设备之间的通讯是确保生产流程顺畅、高效运行的关键。本文详细介绍了安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯的具体方法。 一&#xff0e;软硬件需求 1.一台安川MP3300CPU301&#xff0c;其IP地址是192.…

android11 usb摄像头添加多分辨率支持

部分借鉴于&#xff1a;https://blog.csdn.net/weixin_45639314/article/details/142210634 目录 一、需求介绍 二、UVC介绍 三、解析 四、补丁修改 1、预览的限制主要存在于hal层和framework层 2、添加所需要的分辨率&#xff1a; 3、hal层修改 4、frameworks 5、备…

OceanBase 首席科学家阳振坤:大模型时代的数据库思考

2024年 OceanBase 年度大会 即将于10月23日&#xff0c;在北京举行。 欢迎到现场了解更多“SQL AI ” 的探讨与分享&#xff01; 近期&#xff0c;2024年金融业数据库技术大会在北京圆满举行&#xff0c;聚焦“大模型时代下数据库的创新发展”议题&#xff0c;汇聚了国内外众多…

Java的评论大冒险:用代码征服API数据

在一个充满数字奥秘的虚拟世界里&#xff0c;Java勇士正准备踏上他的新征程&#xff1a;获取商品评论的API数据。这不仅是一次技术的挑战&#xff0c;更是一次与时间赛跑的较量。Java勇士&#xff0c;这位编程界的探险家&#xff0c;打开了他的IDE&#xff0c;准备开始这场冒险…

什么是感知与计算融合?

感知与计算融合&#xff08;Perception-Computing Fusion&#xff09;是指将感知技术&#xff08;如传感器、摄像头等&#xff09;与计算技术&#xff08;如数据处理、人工智能等&#xff09;有机结合&#xff0c;以实现对环境的更深层次理解和智能反应的过程。该技术广泛应用于…

进程间通信大总结Linux

目录 进程间通信介绍 进程间通信目的 进程间通信发展 进程间通信分类 管道 System V IPC POSIX IPC 管道 什么是管道 匿名管道 用fork来共享管道原理 站在文件描述符角度-深度理解管道 管道读写规则 管道特点 命名管道 创建一个命名管道 匿名管道与命名管道的区…

【leetcode|哈希表、动态规划】最长连续序列、最大子数组和

目录 最长连续序列 解法一&#xff1a;暴力枚举 复杂度 解法二&#xff1a;优化解法一省去二层循环中不必要的遍历 复杂度 最大子数组和 解法一&#xff1a;暴力枚举 复杂度 解法二&#xff1a;贪心 复杂度 解法三&#xff1a;动态规划 复杂度 最长连续序列 输入输…

长短期记忆网络(Long Short-Term Memory,LSTM)

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 长短期记忆网络&#xff08;Long Short-Term Memory&#xff0c;简称LSTM&#xff09;是一种特殊的循环神经网络&#xff08;Recurrent Neural Network&#xff0c;简称RNN&#xff09;架构&#…