首页 > 数据库 >Redis和MySQL如何保持数据一致性?强一致性,弱一致性,最终一致性

Redis和MySQL如何保持数据一致性?强一致性,弱一致性,最终一致性

时间:2023-01-17 19:05:30浏览次数:50  
标签:缓存 删除 写入 数据库 Redis MySQL 一致性 数据


  • 强一致性,
    任何一次读都能读到某个数据的最近一次写的数据。
    系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。
  • 弱一致性,
    据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。
    最终一致性就属于弱一致性。
  • 最终一致性
    不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。
    最终两个字用得很微妙,因为从写入主库到反映至从库之间的延迟,可能仅仅是几分之一秒,也可能是几个小时
    简单说,就是在一段时间后,节点间的数据会最终达到一致状态。

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

我们通常使用redis集成springboot做数据缓存的时候,一般只是将数据存放到缓存中,设置过期时间。
问题:
如果来缓存失效前,修改了数据库,那就会出现,缓存和mysql数据不一致的情况。因为redis存在,请求就会直接返回redis缓存中的数据。

1.先更新数据库,再更新缓存(不建议)

A修改数据,B修改数据,但是A在修改完数据后,B立马修改,由于网络原因可能造成b先修改了缓存数据,a再修改缓存。这样缓存中的数据就是a请求修改后的数据,这样就造成了数据不一致的情况。

2.先删缓存,再更新数据库

如果先删除缓存,但是数据还没写入mysql,就有请求来读取,发现缓存没有数据,就会把旧数据再写入缓存,还是会造成数据不一致的情况。
解决:
延时双删策略
在数据库更新前删除缓存,然后对数据库进行写入操作,数据库更新完成后再删除再次删除缓存,目的是删除可能后来的读取请求写入缓存的脏数据。第二次删除之前可以休眠几秒。

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

如果线程修改了数据库,然后线程挂了,导致缓存没有删除,那么在缓存失效前,读取的是缓存中的旧数据。(但是这个比较极端就不考虑了)
①此时缓存刚好失效

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

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

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

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

①更新数据库

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

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

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

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

Redis和MySQL如何保持数据一致性?强一致性,弱一致性,最终一致性_mysql

参考博客:https://baijiahao.baidu.com/s?id=1706150811910444110&wfr=spider&for=pc


标签:缓存,删除,写入,数据库,Redis,MySQL,一致性,数据
From: https://blog.51cto.com/u_15601494/6017713

相关文章

  • 前后端项目,前端账户密码输入正确,无法登陆,redis报错。
    前后端项目,前端账户密码输入正确,无法登陆,redis报错。最近在学习公司的项目的时候,早上过来发现,项目启动失败,或者启动成功后但是,输入账户密码无法登录。问题:发控制台报错,好像......
  • go 使用redis
       import(redigo"github.com/gomodule/redigo/redis")  funcNewPool()*redigo.Pool{//return&redigo.Pool{//MaxIdle:3,......
  • mysql timestampdiff 计算二个时间的间隔
    selecttimestampdiff(MINUTE,createDate,now())asinteralFROMtable;   说明:上面的是计算createDate与now()之间相间多少分钟。语法:TIMESTAMPDIFF(unit,da......
  • MySQL的索引
    索引概述介绍索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就......
  • Redis 接管 Session
    在多台服务器中,会遇到Session共享的问题。之前用的实体服务器,都在同一局域网,很好解决。但是迁移到AWS服务器后,不再满足同一局域网。决定用ElastiCacheRedis来管......
  • 物理机安装mysql8, 修改数据库目录
    自动安装mysql,并修改数据库目录. #!/bin/bash#mysql官方下载路径:https://dev.mysql.com/downloads/mysql/#配置dnf源mkdir-p/etc/yum.repos.d/backup&&mv......
  • mysql常用语句
    createtabletable_name(namevarchar(20)comment'姓名',ageintcomment'年龄',numbigintcomment'数值')comment'测试';insertintotable_namev......
  • 修改mysql时区
    方法一:1.首先使用命令:mysql>showvariableslike‘%time_zone%’;±-----------------±-------+|Variable_name|Value|±-----------------±-------+|system......
  • 数据库实践丨使用MTK迁移Mysql源库后主键自增列导致数据无法插入问题
    摘要:用户使用Mogdb2.0.1版本进行业务上线测试,发现在插入数据时,应用日志中提示primarykey冲突,用户自查业务SQL没有问题,接到通知后,招手处理故障。本文分享自华为云社区《​......
  • 【数据库数据恢复】华为云mysql数据库表被truncate,部分表数据被delete的数据恢复案例
    数据库数据恢复环境:华为云ECS,linux操作系统;mysql数据库,实例内数据表默认存储引擎为innodb。数据库故障:在执行数据库版本更新测试时,用户误将本应在测试库测试的sql脚本执......