【实践篇】Redis缓存和数据库一致性问题

news2024/11/29 16:33:29

Redis缓存和数据库一致性问题

文章目录

  • Redis缓存和数据库一致性问题
  • 0. 前言
    • 参考资料
  • 1. 缓存和数据库的数据不一致是如何发生的?
    • 1. 删除数据的情况:
    • 2. 修改数据的情况:

在这里插入图片描述

0. 前言

确保缓存和数据库之间的数据一致性是一项挑战,这需要考虑的因素包括更新策略、操作顺序以及是否引入消息队列等等。

  1. 更新缓存还是删缓存?
    一般来说,推荐的做法是删除缓存,而不是更新缓存。原因是更新缓存会引入更复杂的一致性问题。例如,如果在更新缓存之前,数据库的数据已经发生了变化,那么更新后的缓存数据将是过时的。另一方面,如果删除了缓存数据,那么下次请求时,如果缓存中没有数据,就会去数据库中查找,并将查找的结果存入缓存,这样可以确保缓存中的数据是最新的。

  2. 先更新数据库,再删除缓存,还是先删除缓存,再更新数据库?
    常见的推荐做法是先更新数据库,再删除缓存。原因是如果先删除缓存,那么在缓存删除后到数据库更新这段时间里,新的请求可能会将旧的数据重新加载到缓存中,导致数据不一致。

  3. 为什么要引入消息队列保证一致性?
    引入消息队列的目的是异步处理数据更新和缓存删除操作,减少这两个操作之间的时间差,从而降低数据不一致的风险。另外,消息队列还可以提供重试机制,以应对因为临时的故障导致的操作失败。

  4. 延迟双删会有什么问题?要不要用?
    延迟双删是指先删除缓存,再更新数据库,然后延迟一段时间后再次删除缓存。这种策略的目的是防止在更新数据库后新的请求将旧的数据加载到缓存中。但是,这种策略有一个问题,就是需要确定合适的延迟时间,如果延迟时间过短,可能无法阻止旧数据被加载到缓存中;如果延迟时间过长,可能会导致缓存的数据过期。因此,是否使用这种策略取决于具体的应用场景和需求。

题。

参考资料

  1. Redis官方文档:https://redis.io/
  2. Redis实战(书籍)
  3. Redis设计与实现(书籍)

1. 缓存和数据库的数据不一致是如何发生的?

首先,我们需要明确"数据的一致性"的具体含义。在这里,一致性包括两种情况:

当缓存中存在数据时,缓存的数值应与数据库中的值相同;
当缓存中没有数据时,数据库中的值必须是最新的。

不符合这两种情况的情况就属于缓存和数据库之间的数据不一致问题。

然而,缓存数据不一致的发生情况以及相应的应对方法会根据缓存的读写模式而异。根据是否接受写请求,我们可以将缓存分为读写缓存和只读缓存。

对于读写缓存而言,如果需要对数据进行增删改操作,就需要在缓存中进行,并根据所采取的写回策略决定是否同步写回数据库。同步直写策略要求在写入缓存时同时将数据同步写回数据库,以保持缓存和数据库中的数据一致。异步写回策略则表示在写入缓存时不立即同步写回数据库,而是等到数据从缓存中淘汰时再写回数据库。然而,如果在数据还未写回数据库时缓存发生故障,那么数据库将无法获取最新的数据。

因此,对于读写缓存来说,要保证缓存和数据库的数据一致性,需要采用同步直写策略。但需要注意的是,采用该策略时需要同时更新缓存和数据库。因此,在业务应用中需要使用事务机制,确保缓存和数据库的更新具有原子性,即要么同时更新,要么都不更新并返回错误信息以进行重试。否则,无法实现同步直写。

当然,在某些场景下,对于数据一致性的要求可能不是那么高,例如缓存的是电商商品的非关键属性或短视频的创建或修改时间等。这种情况下,可以使用异步写回策略。

接下来,我们来讨论只读缓存。对于只读缓存,如果有数据新增,会直接写入数据库;而对于有数据修改或删除的情况,需要将只读缓存中的数据标记为无效。这样的处理方式会导致缓存缺失,当应用再次访问这些增删改的数据时,由于缓存中没有相应的数据,就会从数据库中读取数据并将其存入缓存。这样,后续再次访问数据时就可以直接从缓存中读取。

以java向MySQL中写入和修改数据为例,下图展示了数据的增删改操作具体过程:

java-> MySQL
  Insert          数据X直接在数据库中新增
  Update          数据X直接在数据库中修改
  Delete          数据X直接在数据库中删除

如果执行的是修改或删除操作,还会删除缓存中的数据X。

通过图中可以看出,无论是新增、修改还是删除数据X,java上运行的应用都会直接在数据库中进行相应的操作。当然,如果应用执行的是修改或删除操作,还会从缓存中删除数据X。这个过程可以确保缓存和数据库的数据一致性。

1. 删除数据的情况:

当应用执行删除操作时,需要在数据库中删除相应的数据,并且还需要在缓存中删除对应的数据。如果删除数据库操作成功,但在删除缓存时发生错误,就会导致数据不一致的问题。此时,数据库中的数据已经被删除,而缓存中的数据仍然存在,从而导致缓存和数据库的数据不一致。

举个例子来说明这种情况:假设应用要删除数据X的值,首先成功地从数据库中删除了X,但在删除缓存中的X时遇到了错误。这种情况下,数据库中的X已经被删除,但缓存中仍然存在X的数据。如果此时另一个并发请求访问X,根据正常的缓存访问流程,它会首先在缓存中查询X,但由于缓存中仍然存在,它会读取到已经被删除的数据X,导致数据不一致。

2. 修改数据的情况:

在执行数据修改操作时,应用需要先更新数据库中的数据,然后再删除缓存中的数据。如果这两个操作无法保证原子性,就可能出现数据不一致的问题。假设应用先更新数据库,然后再删除缓存,如果在删除缓存时遇到错误,就会导致数据库中的数据是新值,而缓存中的数据是旧值,从而导致数据不一致。

举个例子来说明这种情况:应用要将数据X的值从10更新为3,首先成功地更新了数据库中的值,然后在删除缓存中的X时遇到错误。这种情况下,数据库中X的新值为3,但缓存中X的值仍然是旧值10,导致数据不一致。如果此时有其他并发请求来访问X,按照正常的缓存访问流程,它会先在缓存中查询,但由于缓存中仍然存在,它会读取到旧值10,进一步导致数据不一致。

当我们考虑缓存和数据库的一致性问题时,除了操作失败的情况,还需要考虑并发问题。并发问题可能会导致缓存和数据库之间的数据不一致。让我们来看一下这两种情况:

  1. 并发写: 如果有两个并发的写操作,一个写操作先更新数据库,然后更新缓存,另一个写操作在第一个写操作更新数据库后和更新缓存前更新了数据库和缓存,那么最后缓存中的数据将是第一个写操作的数据,而数据库中的数据是第二个写操作的数据,这就导致了数据不一致。

  2. 写后读: 如果一个写操作先更新了数据库,然后在更新缓存之前,一个读操作读取了数据库并将数据加载到了缓存,那么即使写操作后来更新了缓存,缓存中的数据也是旧的数据,这也会导致数据不一致。

为了解决这些问题,我们可以采用以下策略:

  1. 使用分布式锁: 我们可以在更新数据库和缓存时使用分布式锁,确保每次只有一个写操作可以执行。这样可以避免并发写的问题,但是会降低系统的并发性能。

  2. 先删除缓存,再更新数据库: 这是一种常见的策略,它可以避免写后读的问题。具体来说,我们先删除缓存,然后更新数据库。这样,如果在更新数据库后有一个读操作,由于缓存中没有数据,读操作会从数据库中读取最新的数据并加载到缓存中。

  3. 使用消息队列: 我们可以将更新缓存的操作放入消息队列中,确保更新数据库和更新缓存的操作按照正确的顺序执行。这样可以避免并发写和写后读的问题,但是会增加系统的复杂性。

以上只是一些基本的策略,具体的实现可能会根据业务需求和系统环境的不同而有所不同。总的来说,维护缓存和数据库的一致性需要综合考虑多种因素,包括但不限于如何更新数据、操作的顺序、是否引入消息队列以及如何处理并发等问题。

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

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

相关文章

【Kafka系列】(一)Kafka入门

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 Kafka是什么? 一句话概括:「Apache Kafka 是一款开源的消息引擎系统」 什么是消息引擎系统&#…

软件测试代码覆盖率

在<professional software testing with visual studio 2005 team system tools for software developer>中提到了代码覆盖率&#xff0c;我很久没有去书店了&#xff0c;不知道是不是出了新的版本&#xff0c;觉得书里面关于代码覆盖率方面的知识有些地方没有讲&#xf…

RobotFramework自动化测试框架系列学习----(二)库与关键字

一、类库和标准库 在RIDE中&#xff0c;按F5可查看库和关键字标准库 &#xff08;RF自带的库&#xff0c;不需要额外安装&#xff09; Buitln 测试库 Collections 集合库 DateTime 时间库 Screenshot 截屏库 存放位置&#xff1a;Python37\Lib\site-packages\robot\libraries …

点成案例丨比浊仪助力牙周炎诱发因素研究

牙周炎概述 牙周炎&#xff08;Periodontitis&#xff09;是一种炎症性疾病&#xff0c;其主要特征为牙周袋的形成及袋壁的炎症、牙槽骨吸收而导致牙龈与牙齿分离、牙齿逐渐松动或掉落等。牙周炎主要是由积聚在牙龈及其附近牙面、齿颈缘的牙菌斑内细菌所分泌的毒素令牙周组织发…

Linux命令200例:xargs标准输入的数据作为参数传递使用

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0…

DeepFaceLab和DeepFaceLive下载地址

DeepFaceLab和DeepFaceLive下载地址 项目地址&#xff1a;https://github.com/iperov/DeepFaceLab 下载地址&#xff1a;https://disk.yandex.ru/d/7i5XTKIKVg5UUg 需要科学上网 还有一个其他版本的磁力 magnet:?xturn:btih:e7ffdcb4ada863de9504f2a741f924dcd56ab84a&…

智安网络|加强软件供应链安全保障:共同抵御威胁的关键路径

在当今数字化时代&#xff0c;软件供应链安全成为了一个备受关注的话题。各行各业都依赖于软件产品和服务来支持其业务运营。然而&#xff0c;随着供应链的不断扩大和复杂化&#xff0c;软件供应链安全问题也日益突出。那么应该如何解决&#xff1f; 首先&#xff0c;软件供应…

开了抖店后就可以直播带货了吗?想在抖音带货的,建议认真看完!

我是王路飞。 关于抖店和直播带货的关系&#xff0c;其实很多人经常搞不清楚。 不然的话&#xff0c;也不会有这个问题的出现了&#xff1a;开了抖店后就可以直播带货了吗&#xff1f; 在我看来&#xff0c;这个问题很简单&#xff0c;但在不了解抖音电商和直播带货其中门道…

postgres源码解析55 Brin Index--2(brinbuild流程)

上一篇讲解了brin index的基本概念以及页布局postgres源码解析54 Brin Index–1&#xff0c;后续会从源码角度对索引的构建、维护等方面进行深入讲解。 1 关键数据结构 2 brinbuild执行流程图 3 brinbuild 函数详解 1 首先调用brin_matepage_init初始化brin meta元数据页&…

【Day_29慢就是快】代码随想录-二叉树-二叉树的所有路径

给定一个二叉树&#xff0c;返回所有从根节点到叶子节点的路径。 思路 求根节点到叶子节点的路径&#xff0c;需要前序遍历&#xff0c;方便让父节点指向孩子节点&#xff0c;找到对应的路径。 使用递归方法做前序遍历&#xff0c;递归与回溯是一家的。 递归 1. 递归参数及返…

C++ Opencv视频检测

使用OpenCV进行视频检测的一般步骤如下&#xff1a;导入OpenCV库和视频文件。 对每一个视频帧进行对象检测。可以使用诸如Haar特征分类器、Cascade分类器或深度学习模型等技术进行对象检测。 #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> …

OpenLdap +PhpLdapAdmin + Grafana docker-compose部署安装

目录 一、OpenLdap介绍 二、PhpLdapAdmin介绍 三、使用docker-compose进行安装 1. docker-compose.yml 2. grafana配置文件 3. provisioning 四、安装openldap、phpldapadmin、grafana 五、配置OpenLDAP 1. 登陆PhpLdapAdmin web管理 2. 需要注意的细节 内容介绍参考…

Linux系统的安装

文章目录 1 Linux介绍1.1 Linux是什么1.2 Linux的特点1.3 Linux的应用1.4 Linux的发行版本1.5 Linux的Shell 2 Linux安装2.1 安装方式2.2 什么是VMware2.3 VMware主要功能2.4 什么是CentOS2.5 VMware与CentOS与Linux的关系2.6 VMware安装CentOS的步骤 1 Linux介绍 1.1 Linux是…

【前沿资讯】2023年最新遥感类SCIE/ESCI期刊影响因子汇总

6月28日&#xff0c;Clarivate发布了最新的JCR报告&#xff0c;公布了期刊的最新SCIE影响因子&#xff0c;并首次发布了ESCI期刊的影响因子。其中归入遥感“remote sensing”类的SCIE期刊有33本&#xff0c;归入ESCI期刊的有25本&#xff0c;以下分别为它们的相关指标。 表1 遥…

【LeetCode75】第四十六题 除法求值

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们多个二维数组形式的除法等式&#xff0c;在二维数组里有两个字符串&#xff0c;表示同名的未知数&#xff0c;另一个数组中对应…

SpringBoot 集成 Canal 实现监听MySQL表数据

SpringBoot 集成 Canal 准备工作什么是 CanalCanal 在 Spring Boot 中的作用和优势准备工作安装和配置 MySQL 数据库 安装Canal项目集成导入依赖添加配置信息创建监听类测试 准备工作 什么是 Canal Canal 是阿里巴巴开源的基于数据库增量日志解析的数据同步和订阅组件&#x…

写得了代码,焊得了板!嵌入式开发工程师必修之代码管理方案(下)

目录 极狐GitLab嵌入式开发场景解决方案 3.1 高可用部署与灾备 3.2 组织管理 3.3 分支策略 3.4 分支保护 3.5 推送规则 3.6 代码评审 3.7 数据保护 3.8 其他相关 本文来自 武让 极狐GitLab 高级解决方案架构师 &#x1f4a1; 前两篇文章&#xff0c;作者介绍了嵌入式开…

接口自动化测试系列-接入测试平台

测试平台目录 测试平台自建源码 后台核心代码 def add_api(kwags):"""插入api数据"""try:join_info CaseApi(namekwags.get("name"), httpTypekwags.get("httpType"),headerskwags.get("headers") if kwags.ge…

Rhinoceros(犀牛)使用技巧:有关曲线和曲面的分析

Rhinoceros&#xff08;犀牛&#xff09; for Mac破解版是一款功能强大的高级建模软件&#xff0c;可以创建、编辑、分析、提供、渲染、动画与转换 NURBS 线条、曲面、实体与多边形网格。不受精度、复杂、阶数或是尺寸的限制&#xff0c;在本篇文章中&#xff0c;为您介绍的是有…

AI与科学知识共生的桥梁,在未来AI会不会取代大学呢?

原创 | 文 BFT机器人 2023年&#xff0c;随着GPT在各行各业的爆发&#xff0c;“是否能将GPT用于科研场景”成为了一个水到渠成的问题。当ChatGPT超越大部分人类在高考、SAT、美国法考、医考等领域取得令人咋舌的高分后&#xff0c;人们对于GPT驱动科研的兴趣愈发高涨。截止本…