请选择 进入手机版 | 继续访问电脑版

[数据库其它] MySQL与Redis怎样 保证数据划一 性详解

[复制链接]
查看125 | 回复13 | 2021-9-12 07:47:05 | 显示全部楼层 |阅读模式

前言

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

MySQL与Redis怎样
保证数据划一

性详解

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

同等 性方案

在现实 项目开辟 中必要 保证数据库和缓存中的数据同等 ,否则人家充值了100块,不断革新 却还是表现 0.01元,岂不是尴尬?从理论上来说,为缓存设置过期时间是终极 保证数据同等 性的办理 方案,采用这种方案的话,全部 的写操作都是以数据库为准,假如 数据库写入成功但是缓存更新失败,只要缓存到过期时间之后后面读缓存时天然 会在数据库中读取新的值然后更新缓存。接下来探究 的思绪 紧张 的方向是在不依赖 为缓存设置过期时间的条件 下怎样 保证数据同等 性。这里紧张 探究 三种方案:

  1. ①先更新数据库,再更新缓存
  2. ②先删除缓存,再更新数据库
  3. ③先更新数据库,再删除缓存
复制代码

先更新数据库再更新缓存

这种方案是广泛 被反对的(在我的认知范围中~),为啥呢?为啥这种方案就被反对呢?缘故原由 紧张 有两方面,请听我细细道来:

起首 从数据安全方面思量 ,假如 同时有哀求 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中获取数据,假如 获取成功直接返回,假如 没有获取成功,则从数据库中获取,成功后放到缓存中,更新数据时应该先把数据存到数据库中成功后再让缓存失效。**原文如下

MySQL与Redis怎样
保证数据划一

性详解

  1. 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.
  2. 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的时间可以临时 忽略),只有这种环境 下④才大概 比⑤先发声,但是数据库的读操作要远比写操作快的多,不然做读写分离干嘛呢?以是 这种环境 发生的概率黑白 常非常非常的低,但是假如 逼迫 症患者出现必须要办理 怎么办呢?就可以采用给缓存设置过期时间或者采用第二种方案的延时双删策略,保证读哀求 完成之后在举行 删除操作。

末了 的题目

还有题目 呀,就是终极 办理 方案三大概 出现的极低概率的数据不同等 的方案是采用方案二的延时双删策略,但是 在方案二中也说了,假如 出现缓存删除失败的环境 咋办?那不是还会出现数据不同等 的题目 吗?这个题目 到底怎样 办理 呢?这里提供一个重试机制,删除失败就重试一次呗,这里提供一种重试的方案。

  1. ①更新数据库
  2. ②由于各种原因缓存删除失败
  3. ③将删除失败的缓存放入消息队列中
  4. ④业务代码从消息队列中获取需要删除的key
  5. ⑤继续尝试删除操作,直到成功
复制代码

MySQL与Redis怎样
保证数据划一

性详解

总结

到此这篇关于MySQL与Redis怎样 保证数据同等 性的文章就先容 到这了,更多干系 MySQL与Redis数据同等 性内容请搜索 脚本之家从前 的文章或继续欣赏 下面的干系 文章渴望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 又见阿凡提彻 | 2021-9-12 12:41:14 | 显示全部楼层
admin楼主发几张靓照啊!
回复

使用道具 举报

avatar 追上前面的 | 2021-9-12 13:03:47 | 显示全部楼层
视死如归的架势啊!
回复

使用道具 举报

avatar 123457191 | 2021-9-12 17:50:34 | 显示全部楼层
帖子很有深度!
回复

使用道具 举报

avatar 123457287 | 2021-9-15 22:17:52 | 显示全部楼层
admin楼主最近很消极啊!
回复

使用道具 举报

avatar 我就是但丁徊 | 2021-9-18 06:18:18 | 显示全部楼层
经典!
回复

使用道具 举报

avatar 素舒 | 2021-9-20 14:09:47 | 显示全部楼层
今天的心情很不错啊
回复

使用道具 举报

avatar fsxjjv | 2021-10-4 09:40:16 | 显示全部楼层
论坛的人气不行了!
回复

使用道具 举报

avatar Qian723 | 2021-10-5 06:45:54 | 显示全部楼层
admin楼主的头像是本人吗?
回复

使用道具 举报

avatar 淡然一笑wwc | 2021-10-5 06:45:58 | 显示全部楼层
admin楼主好聪明啊!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则