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

《统计学习方法》——李航 学习大纲 最近在学习李航写的统计学习方法概论, 每一章都用xmind理清了思路,括号里是书里的公式,第一次写博文,敬请指教~~~~ 第一章 统计学习方法论 第二章 感知机 每个方法其实只需要着重掌握三要素和输入输出就可以了,主要看模型、策略和算法。 感知机主要是二类分类的线性分类模型。 看到后面会注意感知机和支持向量机的区别。 第三章 k近 阅读详情

前言

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

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

一致性方案

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

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

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

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

先更新数据库再更新缓存

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

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

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

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

先删缓存再更新数据库

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

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

# 伪代码
def delay_delete():
    redis.delete('name')  # 更新数据库之前先删除缓存
    sql = 'update info set name='lili' where id=1;'  # 更新数据库
    cursor.execute(sql)  
    time.sleep(1)  # 如果mysql是主从架构则休眠主从延时的时间再多几百ms
    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

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

海康安防平台接口调试指南:从签名生成到Vue项目集成 本文详细解析了海康安防平台接口认证规则,从签名生成到Vue项目集成的完整流程。通过核心机制解析、签名工具使用技巧及Vue项目中的优雅集成方案,帮助开发者高效完成接口调试,避免常见问题。特别适合需要将海康安防平台接口集成到Vue项目中的开发者参考。 阅读详情

相关推荐

Cesium进阶学习四、shadertoy(着色器)

Cesium进阶学习着色器

程迷学习的博客 4325

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

在高并发的场景下,大量的请求直接访问MySQL很容易造成性能问题。所以,我们都会用Redis来做数据的缓存,削减对数据库的请求。但是,MySQL和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。数据不一致的原因导致数据不一致的原因1、在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。2、所以,就需要使用redis做一个缓冲操作,让请求先访问到redi...

码农code之路 1242

DIC新手避坑指南:压缩实验中的应变测量常见错误与数据校验技巧

本文为DIC技术新手提供了压缩实验中应变测量的全面避坑指南。文章系统梳理了从试样尺寸录入、散斑质量到数据后处理中应变方向与符号混淆、数据插值对齐等常见错误,并分享了基于MATLAB的自动化数据校验与可视化对比技巧,帮助建立可靠的实验数据分析SOP,确保DIC测量结果的准确性。

weixin_29313423的博客 115

如何保持mysql和redis数据一致性?

在进行写操作时,先更新 MySQL 里的数据,再删除 Redis 里该数据对应的缓存。在读操作时,先从 Redis 缓存中获取数据,若没有则从 MySQL 查找,然后将查找到的数据写入 Redis 缓存中。例如,使用 Binlog 和 Canal 进行 MySQL 数据的订阅和读取,并将订阅到的数据写入 Redis 缓存中。在进行写操作时,同时更新 MySQL 和 Redis 中的相应数据。这种方式保持了 MySQL 和 Redis 数据的强一致性,但可能会降低写操作的性能和增加系统的复杂度。

weixin_44144370的博客 2839

视频教程-SAP S4 HANA FICO COPA 获利能力分析-ERP

SAP S4 HANA FICO COPA 获利能力分析 从业超过8年的SA...

weixin_33456805的博客 1444

华为OD机试真题2025双机位C卷 Python&JS 实现【卡牌游戏】

小明正在尝试一种新的牌游戏。游戏规则只如下:首先,小明拿到一张写有数字m的牌。 然后,他会拿到另外n张牌,上面分别写有不同的数字,牌排成一排。小明的目标是从这排牌中找到一串连续的牌,这些牌上数字的总和可以被 m整除。你的任务是判断小明是否可以完成这个目标。

MISAYAONE的博客 404

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

在高并发的场景下,大量的请求直接访问MySQL很容易造成性能问题。所以,我们都会用Redis来做数据的缓存,削减对数据库的请求。但是,MySQL和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。

dream317 2364

Python3+PCAN-USB基于PCAN-Basic二次开发实现上位机功能

一、环境搭建 1.概述 本文主要是通过Python3与CAN总线工具PCAN-USB基于官方PCAN-Basic库实现CAN总线消息读写功能。 2.PCANBasic.py和PCANBasic.dll下载地址 https://www.peak-system.com/fileadmin/media/files/pcan-basic.zip 3.Python安装 下载地址:https://www.p...

测试领域技术分享 5186

redis和MySQL如何保证数据的一致性

同一份数据同时保存在redis和MySQL,那么数据发生变化的时候就需要同时更新这两个存储,但是更新会有前后且不具有原子性,就会出现数据一致性问题。先删除缓存,再更新数据库:也会存在极端情况,删除redis和更新数据库之间有线程访问,也会存在数据不一致的问题。redis是用来实现应用与数据库之间读操作的缓存层,目的是减少数据库的IO,还可以提升数据的IO性能。注:方法一和二都保证了数据的最终一致性,但是不保证短时间内数据一致。先更新数据库,再更新缓存:如果缓存更新失败,那么数据就会不一致。

Danny的博客 1272

996引擎 - 【任务系统】和【cfg_newtask.xls】

996这个任务系统仅用于控制主界面左上角的【任务列表】,不包含具体任务的业务逻辑。任务列表有多个任务时支持上下滑动,可以调用接口将指定任务【置顶】任务列表中,每个任务一行,分标题和(当前状态对应的)内容两部分,点击能触发事件具体的任务系统业务逻辑,需要自己写代码实现。(配合996提供的任务接口和触发,实现更新任务列表)

灵台方寸山斜月三星洞 1500

PyTorch 最新安装教程(2021-07-27)

PyTorch 最新安装教程(2021-07-27)前言1. 安装 Anaconda2. 检查显卡,更新驱动3. 创建PyTorch环境4. 配置清华TUNA镜像源5. 安装 PyTorch6. 测试 前言 万事开头难! 这句话又一次被我验证。 记得前不久刚陷入Tensorflow2.0的安装困境,这一次又被PyTorch 搞哭辽。 孩子太难了o(╥﹏╥)o,不过还好最终成功安装,感谢全网资源,感谢大佬们的博客!被我一次一次试了出来。 1. 安装 Anaconda Anaconda 是一个用于科学计算的 P

全网粉丝30W+,优快云、稀土掘金人工智能领域签约作者,人工智能、大模型、Python 爬虫,商务合作,请私信沟通。 23万+

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

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

hayhead的博客 1331

基于ESP32 蓝牙游戏手柄设计

介绍使用 ESP32 并通过 BLE 通信的 设计手持游戏手柄,包含原理图与代码

DT程序员的博客 2164

Java经典面试题:Redis 和 Mysql 如何保证数据一致性

实时一致性方案:采用“先写 MySQL,再删除Redis”的策略,这种情况虽然也会存在两者不一致,但是需要满足的条件有点苛刻,所以是满足实时性条件下,能尽量满足一致性的最优解。最终一致性方案:采用“先写 MySQL,通过 Binlog,异步更新 Redis”,可以通过 Binlog,结合消息队列异步更新 Redis,是最终一致性的最优解。

wml_JavaKill的博客 4409

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

基于Redis和MySQL的架构,如何保证数据一致性?

今天分享一道一线大厂公司高频面试题。“基于Redis和MySQL的架构,如何保证数据一致性”。这个问题难倒了不少工作5年以上的程序员,难的不是问题本身,而是解决这个问题的思路。另外,我准备了一份500页的PDF面试题解析配套文档,一般情况下,Redis是用作应用程序和数据库之间读操作的缓存,主要目的是减少数据库IO,还可以提升数据的IO性能。如图所示,这是Redis加MySQL的整体架构设计。当应用程序需要去读取某个数据的时候,首先会先尝试去Redis中加载,如果命中就直接返回。如果没有命中,就从数据库查询

Tom弹架构 3176

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Redis 和 Mysql 如何保证数据一致性

Redis 里面,当数据发生变化的时候,需要同时更新 Redis 和 Mysql,由于更新是有先。如果是先删除缓存,再更新数据库,理想情况是应用下次访问 Redis 的时候,发现 Redis。如果先更新数据库,再更新缓存,如果缓存更新失败,就会导致数据库和 Redis 中的数。里面的数据是空的,就从数据库加载保存到 Redis 里面,那么数据是一致的。先不用慌,技术是为业务服务的,所以不同的业务场景,对于技术的选择和方案的设计。都是不同的,所以这个时候,可以反问面试官,具体的业务场景是什么?

sinat_53467514的博客 1000

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

数据一致”一般指的是:缓存中有数据,缓存的数据值=数据库中的值。但根据缓存中是有数据为依据,则“一致”可以包含两种情况:1)缓存中有数据,缓存的数据值=数据库中的值。2)缓存中本没有数据,数据库中的值=最新值(有请求查询数据库时,会将数据写入缓存,则变为上面的“一致”状态)。“数据不一致”:缓存的数据值≠数据库中的值;缓存或者数据库中存在旧值,导致其他线程读到旧数据。一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

JAVA技术博客 3189

基于Redis和mysql架构,如果保证数据一致性

如图所示,是redis+mysql整体架构设计该设计会出现一个问题,如下图所示我们在面试的时候,面试官还可能会问各种没有场景化的纯粹的技术问题,比如说: “你这个最终一致性方案”还是会存在数据不一致的问题啊?那怎么解决?先不用慌,技术是为业务服务的,所以不同的业务场景,对于技术的选择和方案的 设计都是不同的,所以这个时候,可以反问面试官,具体的业务场景是什么?大家一定要记住,某个技术方案不可能适用于所有的业务场景,只有最合适的方案, 没有最优的方案。

小草的博客 1593

Redis和Mysql如何保证数据一致性

由于这个更新是有先后顺序的,并且它不像MySQL里面的多表事务一样,可以满足ACID的事务特性。在理想情况下,应用下次访问Redis的时候,发现Redis里面的数据是空的,就从数据库里面加载并保存到Redis里面。但是在极端情况下,由于删除Redis和更新数据库这两个操作并不是原子的,所以这个过程中,如果有其他线程来访问,还是会存在数据不一致的问题。如果先更新数据库再更新缓存,那么如果缓存更新失败,就会导致数据库中的数据和Redis中的数据不一致。

qq_46130027的博客 610

Mysql和Redis如何保证数据一致性

如何保证数据库和缓存双写一致,下面提供几种方法,来讨论下他们的优缺点。数据一致性没有绝对的保证,要么牺牲性能加锁,要么串行。在高并发下,这些方案都只能做到优化先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。...

drhrht的博客 3857

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

如果是先删除缓存,再更新数据库,理想情况是应用下次访问 Redis 的时候,发现Redis 里面的数据是空的,就从数据库加载保存到 Redis 里面,那么数据是一致的。如图,在这样一个架构中,会出现一个问题,就是一份数据,同时保存在数据库和 Redis 里面,当数据发生变化的时候,需要同时更新 Redis 和Mysql,由于更新是有先后顺序的,并且它不像 Mysql中的多表事务操作,可以满足 ACID 特性。如果先更新数据库,再更新缓存,如果缓存更新失败,就会导致数据库和 Redis。

weixin_63908159的博客 1011
上一篇: 691页,41个版块,终于有阿里大师可以带我吃透Spring源码了
下一篇: Java之父推荐,终于学完了阿里P8开发推荐的Java性能优化文档
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值