MySQL和Redis如何保证数据一致性?

前言

由于缓存的高并发和高性能已经在各种项目中被广泛使用,在读取缓存这方面基本都是一致的,大概都是按照下图的流程进行操作:

但是在更新缓存方面,是更新完数据库再更新缓存还是直接删除缓存呢?又或者是先删除缓存再更新数据库?在这一点上就值得探讨了。

一致性方案

在实际项目开发中需要保证数据库和缓存中的数据一致,否则人家充值了100块,不断刷新却还是显示0.01元,岂不是尴尬?从理论上来说,为缓存设置过期时间是最终保证数据一致性的解决方案,采用这种方案的话,所有的写操作都是以数据库为准,如果数据库写入成功但是缓存更新失败,只要缓存到过期时间之后后面读缓存时自然会在数据库中读取新的值然后更新缓存。接下来探讨的思路主要的方向是在不依赖为缓存设置过期时间的前提下如何保证数据一致性。这里主要探讨三种方案:

①先更新数据库,再更新缓存

②先删除缓存,再更新数据库

③先更新数据库,再删除缓存

先更新数据库再更新缓存
这种方案是普遍被反对的(在我的认知范围中~),为啥呢?为啥这种方案就被反对呢?原因主要有两方面,请听我细细道来:

首先从数据安全方面考虑,如果同时有请求A和请求B同时进行操作,A先更新了数据库的一条数据,随后B马上有更新了该条数据,但是可能因为网络延迟等原因,B却比A先更新了缓存,就会出现一种什么情况呢?缓存中的数据并不最新的B更新过的数据,就导致了数据不一致的情况。

其次从业务场景方面考虑,如果是一个写数据库较多而读数据库较少的业务,如果采用这种方案就会导致数据还没读缓存就会被频繁更新,白白浪费性能。

综合以上两方面的考虑,这种方案果断pass。下面的两种方案就是争议较大的两种方案了,到底是先删缓存再更新数据库还是先更新数据库再删除缓存?

先删缓存再更新数据库
如果同时有一个请求A进行更新操作,请求B进行查询操作,就可能会出现A请求进行写操作前会删除缓存,B请求刚好此时进来发现缓存是空的,B请求就会查询数据库,如果此时A请求的写操作还未完成,B请求查询到的就还是旧的值,还是会将旧的值写入缓存,A请求将新的值写入数据库,此时就会导致数据不一致的问题,如果不采用给缓存设置过期时间的策略,该数据永远都是脏数据。

解决这种情况可以采用延时双删的策略,就是在更新数据库之前先删除缓存,然后对数据库进行写入操作,数据库更新完成之后再次进行删除缓存的操作,目的是删除读请求可能造成的缓存脏数据,第二次删除缓存之前可以休眠几秒,具体时间开发者可以评估一下自己项目读数据业务逻辑的耗时,然后在该耗时基础上加几百ms即可,这么做的目的就是确保读请求结束写请求可以删除读请求造成的脏数据。如果MySQL采用的是读写分离的架构,可能由于主从延时的原因造成数据不一致,可以在写操作完成之后根据主从延时时间休眠一下然后再进行删除缓存的操作。延时双删的伪代码如下:
 

 
  1. # 伪代码

  2. def delay_delete():

  3. redis.delete('name') # 更新数据库之前先删除缓存

  4. sql = 'update info set name='lili' where id=1;' # 更新数据库

  5. cursor.execute(sql)

  6. time.sleep(1) # 如果mysql是主从架构则休眠主从延时的时间再多几百ms

  7. redis.delete('name') # 再次删除缓存

 那会不会存在第二次删除缓存失败的情况呢?如果第二次删除失败,还是会造成缓存和数据库不一致的问题,又如何解决呢?且看下一种方案。

先更新数据库再删除缓存

老外提出了一个缓存更新方案Cache−AsidepatternCache-Aside patternCache−Asidepattern,文章中提到**应用程序应该从cache中获取数据,如果获取成功直接返回,如果没有获取成功,则从数据库中获取,成功后放到缓存中,更新数据时应该先把数据存到数据库中成功后再让缓存失效。**原文如下

If an application updates information, it can follow the write-through strategy by making the modification to the data store, and by invalidating the corresponding item in the cache.

When the item is next required, using the cache-aside strategy will cause the updated data to be retrieved from the data store and added back into the cache.
 

这种方案会不会产生数据不一致的情况呢?比如下述这种情况:

有两个请求A和B,A进行查询同时B进行更新,假设发生下述情况:

①此时缓存刚好失效

②请求A 就会去查询数据库得到一个旧的值

③请求B将新的值写入数据库

④请求B写入成功后删除缓存

⑤请求A将查到的机制写入缓存,产生脏数据...

如果发声上述情况,确实会产生数据不一致的情况,但是XDM想一想,发生这种情况的概率是多少呢?如果先要产生这种结果,就必须有一个条件,就是请求B的操作时间非常短,短到什么程度呢,就是请求B写入数据库的操作要比请求A从数据库中读取数据的速度要快(因为redis非常快,因此操作redis的时间可以暂且忽略),只有这种情况下④才可能比⑤先发声,但是数据库的读操作要远比写操作快的多,不然做读写分离干嘛呢?所以这种情况发生的概率是非常非常非常的低,但是如果强迫症患者出现必须要解决怎么办呢?就可以采用给缓存设置过期时间或者采用第二种方案的延时双删策略,保证读请求完成之后在进行删除操作。

最后的问题

还有问题呀,就是最终解决方案三可能 出现的极低概率的数据不一致的方案是采用方案二的延时双删策略,可是在方案二中也说了,如果出现缓存删除失败的情况咋办?那不是还会出现数据不一致的问题吗?这个问题到底如何解决呢?这里提供一个重试机制,删除失败就重试一次呗,这里提供一种重试的方案。

①更新数据库

②由于各种原因缓存删除失败

③将删除失败的缓存放入消息队列中

④业务代码从消息队列中获取需要删除的key

⑤继续尝试删除操作,直到成功

 

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

          视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取。

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

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

相关文章

什么又是线程呢??

线程: 线程可以并发的执行,但是线程的地址是可以共享的 进程与线程的比较: 进程>线程 线程分三种: 用户线程 只有用户程序的库函数来 用户线程 因为操作系统感知不到 线程,如果有线程在运行,然后不交…

如何使用Python进行数据可视化:Matplotlib和Seaborn指南【第123篇—Matplotlib和Seaborn指南】

如何使用Python进行数据可视化:Matplotlib和Seaborn指南 数据可视化是数据科学和分析中不可或缺的一部分,而Python中的Matplotlib和Seaborn库为用户提供了强大的工具来创建各种可视化图表。本文将介绍如何使用这两个库进行数据可视化,并提供…

element-plus表格,多样本比较,动态渲染表头

问题: 公司给了个excel表格,让比较两个样本之间的数据,并且动态渲染,搞了半天没搞出来,最后让大佬解决了,特此写篇博客记录一下。 我之前的思路是合并行,大概效果是这样: 但是最终…

DataGrip 面试题及答案整理,最新面试题

DataGrip的数据库兼容性和多数据库支持如何实现? DataGrip实现数据库兼容性和多数据库支持的方式包括: 1、广泛的数据库支持: DataGrip支持多种数据库,包括但不限于MySQL, PostgreSQL, SQL Server, Oracle, SQLite, 和MongoDB&a…

小米笔记本出现no bootable devices

原因:硬件松动 解决方案: 1、不妨翻个面敲几下,上下左右晃晃试试 2、这个问题也困扰我好久了 搜了好多答案说是硬盘出了问题 前几次就是摇一摇,拍一拍就好了 后来怎么拍也没有用了 没办法自己动手,买一套螺丝刀&…

Docker----Dockerfile构建微服务镜像

目录 一、关键步骤 二、具体步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 一、关键步骤 1、准备后端jar包(这里以java后端演示) 2、编写Dockerfile 3、构建镜像 4、运行镜像容器 5、测试是否成功 二…

Web前端依赖版本管理最佳实践

本文需要读者懂一点点前端的构建知识: 1. package.json文件的作用之一是管理外部依赖;2. .npmrc是npm命令默认配置,放在工程根目录。 Web前端构建一直都是一个不难,但是非常烦人的问题,在DevOps、CI/CD领域。 烦人的是…

HTTPS证书很贵吗?

首先,我们需要明确一点,HTTPS证书的价格并不是一成不变的,它受到多种因素的影响。其中最主要的因素包括证书的类型、颁发机构以及所需的验证级别。 从类型上来看,HTTPS证书主要分为单域名证书、多域名证书和通配符证书。单域名证书…

pta上的几个例题

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话: 知不足而奋进,望远山而前行&am…

Android Studio实现内容丰富的安卓校园新闻浏览平台

获取源码请点击文章末尾QQ名片联系,源码不免费,尊重创作,尊重劳动 项目编号070 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端: 1.注册登录 2.查看新闻列表 3.查看新闻详情 4.评论新闻 5.收藏新闻 6…

解决VMware无法检测此光盘映像中的操作系统

今天我本想在VMware上安装一个win10系统,可是遇到“无法检测此光盘映像中的操作系统。您需要指定要安装的操作系统。”的错误。报错如下: 图一 遇到的问题 开始还以为是ISO文件有问题,重新下载了几个还是不行(一个ISO文件好几个G&…

APP专项测试

一、介绍 APP测试除了功能测试外,还需要进行一些专项测试来发现更为深层的问题,这些问题主要是针对某个特殊方面进行,如安装卸载升级测试、兼容性测试、弱网测试、中断测试、流量测试、耗电量测试等。 二 、安装卸载升级测试 APP开发后&am…

联想拯救者刃7000K2024游戏电脑主机仅售6999元

这款联想拯救者刀锋7000K 2024游戏电脑主机在京东促销中售价仅为6999元,相比原价7499元有相当大的折扣。 这是一款功能强大的游戏电脑,配备了全新的 15-14400(F) 处理器和 RTX™ 4060 显卡,以及 16GB DDR5 内存和 1TB 固态硬盘。 外观方面&a…

如何有效地组织和管理自己的代码?

如何有效地组织和管理自己的代码? 🧩 🛠️ 如何有效地组织和管理自己的代码? 🧩摘要引言正文1. 使用合适的目录结构2. 模块化设计3. 命名规范4. 版本控制 总结参考资料 博主 默语带您 Go to New World. ✍ 个人主页——…

3.Redis命令

Redis命令 Redis 根据命令所操作对象的不同, 可以分为三大类: 对 Redis 进行基础性操作的命令,对 Key 的操作命令,对 Value 的操作命令。 1.1 Redis 首先通过 redis-cli 命令进入到 Redis 命令行客户端,然后再运行下…

STM32基础--使用寄存器点亮流水灯

GPIO 简介 GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。STM32 芯片的 GPIO被分成很多组,每组有 16 个引脚&#xf…

多源BFS

目录 算法原理 多源BFS步骤: 1、542. 01 矩阵 2、1020. 飞地的数量 3、1765. 地图中的最高点 4、1162. 地图分析 多源BFS(Breadth-First Search,广度优先搜索)是解决边权为1的多源最短路径问题的有效算法。在这种情况下&…

【模拟string函数的实现】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 模拟string函数的实现 浅拷贝 深拷贝 vs和g下string结构的说明 总结 前言 模拟string函数的实现 浅拷贝 深拷贝 总结 前言 世上有两种耀眼的光芒&#…

Java面向对象案例之描述专业和学生(4)

类的方法图 学生类: 属性:学号,姓名,年龄,所学习的专业方法:学习的方法,描述学习状态。描述内容包括姓名、学号、年龄、所学习的专业信息 专业类: 属性:专业编号&#xf…

2024年【天津市安全员C证】考试资料及天津市安全员C证考试试题

题库来源:安全生产模拟考试一点通公众号小程序 天津市安全员C证考试资料根据新天津市安全员C证考试大纲要求,安全生产模拟考试一点通将天津市安全员C证模拟考试试题进行汇编,组成一套天津市安全员C证全真模拟考试试题,学员可通过…