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

news/发布时间2024/5/18 18:35:46

背景


在高并发的业务场景中,因为MySQL数据库是操作磁盘效率比较低,因此大多数情况下数据库都是高并发系统的瓶颈。因为Redis操作数据是在内存中进行,所以就需要使用Redis做一个缓存。让请求先访问到Redis,而不是直接访问MySQL数据库。效果图如下

Untitled

查询数据


上面的业务场景,就是一个典型的MySQL存储数据和Redis缓存数据的业务场景。下面来看看一般的查询流程,如下图:

Untitled

上面的查询流程如下:

  1. 用户请求系统,系统先查询Redis中是否有数据?
  2. 如果Redis中有数据,则直接将缓存中的数据响应给用户。
  3. 如果Redis中没有数据,则取查询MySQL数据库中是否有数据?
  4. 如果MySQL中有数据,则先将数据更新到Redis中,再将数据响应给用户。
  5. 如果MySQL中没有数据,则响应空数据给用户,请求结束。

上面的查询流程很简单,通过先查Redis缓存,避免大量请求访问MySQL数据库,从而大大提高系统响应效率。而且如果Redis中没有而MySQL中有,当从MySQL拿到数据以后,先将数据更新到Redis缓存中,这样下次请求同一份数据的时候就能从Redis中获取了。

更新数据


上面的查询流程是没什么问题,可是数据很有可能会更新。那么更新的时候怎么操作才能保证Redis和MySQL中的数据都更新成功并且一致呢?

下面看看一种常用的解决方案(双删缓存):

Untitled

第一个问题:为什么是删除Redis缓存数据而不是更新数据?

假设我们缓存的数据是要做一个很复杂的计算,而且还不一定能用到。那如果你更新MySQL数据之后去更新Redis缓存不是就很耗时了,而且有可能做无用功。

第二个问题:为什么是先删除Redis缓存数据而不是先更新数据库呢?

我们不妨假设先更新MySQL中的数据,然后再删除缓存。如果更新完MySQL但是删除Redis失败了(别问为什么会失败?系统故障行不行,全球断电行不行?),那下次查询请求过来,因为Redis中有缓存数据,所以直接返回Redis缓存的旧数据了,是不是就出问题了?

那我们再看看,如果先删除Redis缓存,再更新MySQL。如果删除完Redis成功,但是更新MySQL失败。下次查询的时候,查询到Redis缓存发现没有,再去查MySQL,然后更新到Redis,虽然MySQL更新失败了,但是Redis中的数据和MySQL是一致的。

第三个问题:为什么更新完MySQL后还要再删一次Redis缓存呢?

假设我们第一次删完Redis结束,正在更新MySQL但是还没更新成功的时候,这时候有另外一个请求来查询数据。第二个请求查询Redis没有,然后查询MySQL这时候因为MySQL还没更新完,所以查询到的还是旧数据,同时把旧数据更新到Redis中了,等下一个请求再来查询的时候发现Redis有数据,就直接返回旧数据了。

因此更新完MySQL后需要再次删除Redis缓存。这样即使更新数据中间有其他个请求把旧数据更新到Redis中了,因为再次删了Redis缓存中的旧数据,依然能够避免其他请求获取到旧数据。

我们认为数据是否更新成功是以MySQL中的数据为准,因此MySQL还没更新完成前或者更新失败,获取到旧数据不算是问题。所以我们只要保证Redis和MySQL中的数据一致就行。

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

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

相关文章

websocket在线测试

首先先在网页打开测试画面 http://www.jsons.cn/websocket/然后根据系统进行连接按照格式进行连接 连接参数用问好 记得跟token 和 需要的参数 中间用& 并且 值用等号这个是连接上的画面 根据系统 输入参数进行测试 输入参数 和 值 进行测试

eclipse、IDEA配置文档注释

Javadoc:文档注释常用参数常见注释类型 注释含义@author 类的作者@version 类的版本@param 方法的参数@return 方法的返回类型@exception 方法抛出的异常@see 另外参照……@since 从什么时候开始使用的@date 日期@time 时间最常用设置对象 类型(Types)注释标签(类的注释) 方…

[Python]知识点

这篇文章是关于Python各类知识点的小结,包括:特殊标识符、特殊方法、list等。望对大家有帮助! 如果文中阐述不全或不对的,多多交流。【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18031984 出自【进步*于辰的…

Sealos 开源初创公司 Trending 全球 TOP50,中国第二!

今年,Runa Capital (鲁纳资本) 评选出了 2023 年增长最快的 50 家开源创业公司,Sealos 压轴登场,总共有两家中国公司上榜,Sealos 排名第二。Runa Capital (鲁纳资本) 是一家价值 2.7 亿美元的专注于技术的风险投资公司,其创始人和合伙人创建或孵化了资产超过 100 亿美元的…

Go 语言中怎么使用依赖注入

Go 语言中怎么使用依赖注入? 原创 frank Golang语言开发栈 2024-03-31 23:01 北京 听全文大家好,我是 frank。欢迎大家点击标题下方蓝色文字「Golang 语言开发栈」关注公众号。公众号主页点击右上角三个点图标,设为星标,第一时间接收推送文章。文末扫码,加群一起学 Golang…

2-25. 背包 UI 显示

InventoryUI将它拖动到 Canvas 上面的 Inventory增加 Player Slots 我们希望物品被拾取的时候,首先进入下面的背包,然后才进入上面的背包,所以 Player Slots 需要先拖动下面的格子,再拖动上面的格子修改 PlayerBag 的数量因为下面有10个格子,上面有16个格子,所以一共有 2…