Redis学习——数据不一致怎么办?更新缓存失败了又怎么办?

文章目录

    • 引言
    • 正文
      • 读写缓存的数据一致性
      • 只读缓存的数据一致性
        • 删除和修改数据不一致问题
          • 操作执行失败导致数据不一致
            • 解决办法
        • 多线程访问导致数据不一致问题
        • 总结
    • 总结
    • 参考信息

引言

  • 最近面试快手的时候被问到了缓存不一致怎么解决?一开始还是很懵的,因为会默认将自己带到一个错误的前提下,就是数据已经不一致了,你怎么办?可能会想,遍历缓存,删除比对数据是不是一致的。停下来想一下,一般是修改数据库的时候,你应该怎么操作缓存,才能保证缓存的一致性。我就知道要么删除缓存后续重建,要么直接修改缓存,但是我对于这两种场景的方法了解的并不多,今天借这个机会,完全整理一下!

正文

数据一致分几种情况?

  • 缓存中有数据,必须要和数据库中的数据一致
  • 缓存中本身没有数据,数据库中的值必须要是最新的

常见的缓存的策略主要有两种,分别是读写缓存和只读缓存,不同策略保证缓存一致性的方式是不一样。具体如下

读写缓存的数据一致性

  • 读写缓存是对于数据的所有增删改都需要在缓存中进行,然后在采取对应的写回策略。主要有两种写回策略
    • 同步直写策略
    • 异步写回策略

在这里插入图片描述

同步直写策略

  • 写缓存的时候,同步写数据库,缓存和数据库中的数据是一致的
    • 需要通过事务机制,保证缓存和数据库更新的原子性,一般是通过tranactional修饰
      • 要么同步更新成功
      • 要么同步更新失败,下次重试

在这里插入图片描述

异步写回策略

  • 写缓存的时候,不同步写入缓存,等到数据从缓存中淘汰的时候,在写入数据库。
    • 问题
      • 一旦缓存崩溃,在缓存中保存的数据,都会崩溃丢失

在这里插入图片描述

只读缓存的数据一致性

  • 如果有数据更新(数据增加和修改),直接写入数据库,缓存只负责读数据

    • 在下述过程中,可以看到整个过程是涉及到多步骤多线程的,除了对于数据的操作是具有原子性的,不可打断的,其他的读数据包括数据库同步删除缓存中的数据,都会存在可能的中断,或者其他线程切入的操作

    在这里插入图片描述

新增数据情况==》不会出现数据不一致的情况

在这里插入图片描述

  • 但是删除数据或者修改数据不一样了,因为中间涉及到需要删除缓存中的数据,这一步执行失败会导致数据不一致的情况,具体情况见下一节!
删除和修改数据不一致问题
操作执行失败导致数据不一致

操作分析

  • 对于删除或者修改数据的操作,需要同时修改缓存和操作数据库,任何一方都有可能执行失败,因为没有办法保证双方的操作具有原子性,也就是同时失败或者同时成功。
  • 下面按照情况,进行逐个分析,分别是删除缓存失败和删除数据库失败两种情况。

删除缓存失败

  • 在下述过程中,删除缓存失败,导致缓存中保存旧版的数据,数据库是新版的数据,两者不一致。
    在这里插入图片描述

修改数据库失败

  • 修改数据库失败了,删除缓存成功了,但是在二次访问会重建缓存,将数据库中的脏数据,还原到缓存中,还是会出现访问错误数据的情况
    在这里插入图片描述

总结

  • 两种操作执行失败带来的数据不一致的情况如下
不同情况潜在问题
先删除缓存,在更新数据库数据库更新失败,导致请求再次访问缓存时,发现缓存缺失,重建缓存,读到的还是旧的数据
先更新数据库,再删除缓存的缓存删除失败,有请求再次访问缓存时,发现缓存命中,返回脏数据,和数据库不一致
解决办法
  • 在上述两种情况中,如果修改数据库的操作执行失败了,其实不会产生数据不一致的问题,因为缓存中的数据和数据库中的数据是一致的,后续数据库执行相应的处理策略。但是缓存删除执行失败,就不一样了。所以这个解决办法,主要是针对缓存删除失败的情况而指定的。

消息队列重试

  • 在进行删除或者修改数据时,将数据保存到消息队列中,如果执行失败,再通过消息队列重试执行,如果执行成功了,就从消息队列中删除对应的值。

在这里插入图片描述

在重试这段时间,一般是存在数据不一致性,一般是通过如下方式解决

  • 引入分布式锁,加锁,防止其他数据在访问,会降低并发性
多线程访问导致数据不一致问题
  • 因为同步缓存需要两步,分别是修改数据库和缓存,这两个步骤之间一般来说不会加锁,这样会降低并发性,不加锁就意味着会出现多线程访问问题,导致数据的不一致。
  • 按照更新数据库和缓存的先后,主要分为两种情况,这里具体讨论一下

1、先修改数据库,然后在删除缓存访问

时间线程1线程2问题
t1删除数据库中的数据a
t2读取缓存中的数据a,缓存命中,读取到不存在的旧值a线程1尚且没有完全删除缓存值,线程2读到缓存中的脏数据a
t3删除缓存中的数据a

在这里插入图片描述

  • 总结
    • 这种情况持续的时间会很短,因为仅仅只要线程1被切换回来,成功删除缓存中值,就能保证后续数据的一致性,并不需要额外的人工干预。影响小

1、先修改数据库,然后在删除缓存访问

时间线程1线程2问题
t1删除缓存中的数据a
t2读取缓存中的数据a,缓存没有命中,访问旧版数据库,重建缓存a1、线程1没有更新数据库的值,线程2会读到旧值;只要缓存不过期中间,后续所有线程读到的都是旧值
t3更新数据库中的数据a缓存中是旧值,数据库中是新值,两者不一样!

解决办法===延迟双删

  • 修改完数据库之后,再进行一次缓存删除操作,执行两次,保证的缓存的数据重建来自更新之后的数据库
  • 具体指令如下
redis.delKey(x);
db.update(x);
Thread.sleep(N);
redis.delKey(x);

在这里插入图片描述

总结
  • 推荐先删除数据库,再删除缓存,主要原因有以下两点
    • 先删除缓存再删除数据库,导致请求因为缓存缺失而访问数据库,给数据库带来压力
    • 延迟双删的时间不好确定
  • 如果对于数据一致性有强要求
    • 更新数据库的时候,暂停redis缓存发送请求,等都弄完了再发送

总结

  • 不总结不知道,之前知道的太浅薄了,关于redis了解的不够深刻,实际上数据不一致不仅仅是删除或者更新缓存那么简单,中间还会涉及到多线程的问题,因为多个更新数据库和删除缓存并不具有原子性,中间有可能被打断,所以需要分情况进行讨论。
  • 出现数据不一致的情况的以及对应的解决方式有两种,具体如下
数据不一致原因解决办法
删除redis执行失败消息队列重试
多线程导致数据不一致延迟双删策略

参考信息

缓存异常——如何解决缓存和数据库不一致的问题

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于java同步调用多个接口并返回数据

在现代软件开发中,应用程序经常需要与多个远程API接口进行交互以获取数据。Java作为一种流行的编程语言,提供了多种方式来实现这一需求。本文将探讨如何在Java中同步调用多个API接口,并有效地处理和返回数据。 同步调用的必要性 在某些场景下…

音视频推流中使用wireshark进行抓包分析RTMP

一、前期工作 最近使用开发板采集音视频数据合成FLV流后进行推流到PC端(RTMP协议),PC端需要安装对应的nginx以及支持rtmp的nginx,在网上找了教程后安装成功,现在使用wireshark工具对开发板于pc端之间的通信协议进行解析…

【安全系列--处理挖矿】

现象:我们云上waf提示有台服务器存在挖矿行为 解决思路: 1、查看服务器的进程情况 top发现服务的CPU使用率非常高 2、使用性能分析工具perf查看占用的cpu进程 sudo apt install linux-tools-common发现一些kernel进程存在异常 3、使用find查一下这…

Java多线程——模拟接力赛跑

题目: 多人参加1000米接力跑 每人跑100米,换下个选手 每跑10米显示信息 解题思路: 1.必须要用到多线程的锁,否则就会出现三个选手乱跑的情况,我们需要一个一个跑 2.使用给oneRunner上锁的方式更细的控制资源比直接给…

助力汽车半导体产业发展,2025 广州国际新能源汽车功率半导体技术展览会与您相约“羊城”广州

助力汽车半导体产业发展,2025 广州国际新能源汽车功率半导体技术展览会与您相约“羊城”广州 随着半导体技术的升级与发展,功率半导体已经成为推动新能源汽车和智能汽车产业升级的关键因素。汽车不再只是单纯的交通工具,而是逐渐演变为一个智…

【H2O2|全栈】关于CSS(4)CSS基础(四)

目录 CSS基础知识 前言 准备工作 精灵图 概念 属性 案例 浮动 基础属性 清除浮动 案例 预告和回顾 后话 CSS基础知识 前言 本系列博客将分享层叠样式表(CSS)有关的知识点。 接下来的几期内容相对比较少,主要是对前面的内容进…

[数据集][目标检测]车油口挡板开关闭合检测数据集VOC+YOLO格式138张2类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):138 标注数量(xml文件个数):138 标注数量(txt文件个数):138 标注类别…

Linux相关:在阿里云下载centos系统镜像

文章目录 1、镜像站2、下载方式一2.1、第一步打开镜像站地址2.2 下载地址: https://mirrors.aliyun.com/centos/2.3、选择7版本2.4、镜像文件在isos文件夹中2.5、选择合适的版本 3、下载镜像快捷方式 1、镜像站 阿里云镜像站地址 2、下载方式一 2.1、第一步打开镜像站地址 2…

modbus调试助手/mqtt调试工具/超轻巧物联网组件/多线程实时采集/各种协议支持

一、前言说明 搞物联网开发很多年,用的最多的当属modbus协议,一个稳定好用的物联网组件是物联网平台持续运行多年的基石,所以这个物联网组件从一开始就定位于自研,为了满足各种场景的需求,当然最重要的一点就是大大提…

【程序分享】express 程序:可扩展的高级工作流程,用于更快速的从头算材料建模

分享一个 express 程序:可扩展的高级工作流程,用于更快速的从头算材料建模。 感谢论文的原作者! 主要内容 “在这项工作中,我们介绍了一个开源的Julia项目express,这是一个可扩展的、轻量级的、高通量的高级工作流框…

数据驱动型营销与开源 AI 智能名片 O2O 商城系统的融合发展

摘要:本文探讨了数据驱动型营销在现代商业中的重要性,阐述了其在消费者管理和产品管理方面的作用。同时,引入“开源 AI 智能名片 O2O 商城系统”,分析其如何与数据驱动型营销相结合,为企业提供更精准的营销决策和更高效…

Kafka+PostgreSql,构建一个总线服务

之前开发的系统,用到了RabbitMQ和SQL Server作为总线服务的传输层和存储层,最近一直在看Kafka和PostgreSql相关的知识,想着是不是可以把服务总线的技术栈切换到这个上面。今天花了点时间试了试,过程还是比较顺利的,后续…

LineageOS源码下载和编译(Xiaomi Mi 6X,wayne)

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 源码下载 LineageOS官网:https://lineageos.org/ LineageOS源码 github 地址:https://github.com/LineageOS/android LineageOS源码…

创建dataSource错误

说明:记录一次启动项目时的异常,如下: Error starting ApplicationContext. To display the conditions report re-run your application with debug enabled. 2024-09-14 23:27:27.338 ERROR 42260 --- [ main] o.s.boot.SpringA…

leetcode hot100_part4_子串

2024/4/20—4/21 560.和为K的子数组 前缀和哈希表,做二叉树的时候也有这个套路。注意细节,遍历到当前前缀和的时候是先找结果个数还是先加入哈希?应该先找结果个数,不然的话,当前位置也算上了(因为是前缀和…

架构师备考的一些思考(四)

前言 对于数学,我们之前学的是对的,但不是真的,所以我们没有数学思维。 对于计算机,我们学校教的是对的,但不是真的,所以仅仅从学校学习知识的应届毕业生,不论985,211,本科&#xff…

中国初创公司数量下降了98%

近年来,中国风险投资市场的风云变幻,通过IT Juzi(IT桔子)等权威数据服务提供商的透镜,得以清晰展现。数据显示,自2018年的鼎盛时期——拥有51,302家初创公司以来,这一数字在短短五年内急剧下降至…

如何通过网络找到自己想要的LabVIEW知识?

学习LabVIEW或其他编程技术时,无法依赖某一篇文章解决所有问题。重要的是通过多种途径获取灵感,并学会归纳总结,从而逐渐形成系统性的理解。这种持续学习和总结的过程是技术提升的基础。通过网络找到所需的LabVIEW知识可以通过以下几个步骤进…

编写注册接口与登录认证

编写注册接口 在UserController添加方法 PostMapping("/login")public Result login(Pattern(regexp "^\\S{5,16}$") String username,Pattern(regexp "^\\S{5,16}$") String password){ // 根据用户名查询用户User loginUser userS…

第二期: 第二节 , 裸机编程 , gpio

1 首先就是 看原理图: 这里有两个 LED 核心板的原理图。 可以看到 是这个脚。 2 然后就是 查看数据手册。 从 数据手册可以看出 ,一共有这么多的 gpio 组, 但是这些 组 是有复用的&#xf…