iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >MySQL和Redis如何保证数据一致性
  • 370
分享到

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

mysqlredis数据库 2023-08-22 19:08:41 370人浏览 泡泡鱼
摘要

Mysql与Redis都是常用的数据存储和缓存系统。为了提高应用程序的性能和可伸缩性,很多应用程序将mysql和Redis一起使用,其中Mysql作为主要的持久存储,而Redis作为主要的缓存。在这种情况下,应用程序需要确保MySQL和Re

MysqlRedis都是常用的数据存储和缓存系统。为了提高应用程序的性能和可伸缩性,很多应用程序将mysql和Redis一起使用,其中Mysql作为主要的持久存储,而Redis作为主要的缓存。在这种情况下,应用程序需要确保MySQL和Redis中的数据是同步的,以确保数据的一致性。

什么是一致性

“数据一致”一般指的是:缓存中有数据,缓存的数据值=数据库中的值。但根据缓存中是有数据为依据,则“一致”可以包含两种情况:

1)缓存中有数据,缓存的数据值=数据库中的值。

2)缓存中本没有数据,数据库中的值=最新值(有请求查询数据库时,会将数据写入缓存,则变为上面的“一致”状态)。

“数据不一致”:缓存的数据值≠数据库中的值;缓存或者数据库中存在旧值,导致其他线程读到旧数据。

在这里插入图片描述
一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

  • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大
  • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
  • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型

导致数据不一致的原因?

1) 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库;

2)读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新,数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题;

3)这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作。

在这里插入图片描述

应对策略

针对缓存更新问题,提出了一个旁路缓存的缓存更新套路,这个策略分为以下三种场景:

1)失效:应用程序先从缓存取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

2)命中:应用程序从缓存中取数据,取到后返回。

3)更新:先把数据存到数据库中,成功后,再让缓存失效。

不管是先删缓存再更新数据库还是先更新数据库再删缓存,都会导致缓存跟数据不一致问题!

先写MySQL,再写Redis

在这里插入图片描述
先写Redis,再写MySQL
在这里插入图片描述
先删除Redis,再写MySQL
在这里插入图片描述
先写 MySQL,再删除 Redis
在这里插入图片描述
不管是先写数据库,再删除缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。

现有的大部分业务场景下大多采用读写分离的操作来提升数据库吞吐量,但是并发读写访问的时候,对缓存和数据库相互交叉执行操作,则会出现数据不一致问题。

在进行数据更新时,就涉及到先更新缓存还是先更新数据库了,其实两种方式都有数据一致性问题:

举个例子:假如业务A为写请求,业务B为读请求

1.先更新数据库再更新缓存

步骤1:业务A先更新数据库,此时该业务线由于宕机或者其他原因延迟没有继续进行。

步骤2:业务B读取数据,读取的是缓存中的旧数据。

步骤3:业务A恢复过来,更新缓存

可以看到,由于写请求延迟,可能会读到旧的缓存数据。

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

步骤1:业务A先删除缓存

步骤2:业务B进入,业务B发现缓存中没有数据,直接从数据库中进行读取,读到了数据库中的旧数据

步骤3:业务A更新数据库并返回。

可以看到,由于写请求延迟,可能读到旧的数据库数据。

因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。

解决方案

(1)读写请求串行化

最为简单的一种方法,写请求在更新之前需要先获得分布式,获取到锁才能去更新数据库,获取不到则进行等待,超时直接返回更新失败。更新完数据库后更新缓存,如果更新失败,放到内存队列中进行重新尝试。读请求则同样需要获得锁,然判断缓存中是否有数据,有则直接读缓存,没有则直接读数据库,并更新缓存。

这种方案可以保证数据的一致性。但是会降低系统吞吐量(等待时间长),这在需要数据强一致的情况下适用。(银行转账)

(2)删除缓存

  • 1.先删除缓存,后更新数据库
  • 2.先更新数据库,后删除缓存

先删除缓存,后更新数据库,第二步操作失败,数据库没有更新成功,那下次读缓存发现不存在则从数据库中读取,并重建缓存,此时数据库和缓存依日保持一致。

但如果是先更新数据库,后删除缓存,第二步操作失败,数据库是最新值,缓存中是旧值,发生不致。所以,这个方案依旧存在问题。

总之,和前面提到的问题类似,第二步失败依旧有不一致的风险

我们再来看[并发]问题,这个问题是我们需要关注的[重点]

先更新数据库,后删除缓存

依旧是 2 个线程并发[读写]数据

缓存中 X 不存在 (数据库 X = 1)
2.线程 A 读取数据库,得到目值 (X = 1)
3.线程 B 更新数据库 (X = 2)
4.线程 B 删除缓存
5.线程 A 将日值写入缓存 (X = 1)

最终 X的值在缓存中是 1 (日值) ,在数据库中是 2(新值),也发生不一致

这种情况[理论]来说是可能发生的,但实际真的有可能发生吗?

其实概率[很低],这是因为它必须满足 3 个条件

缓存刚好已失效
2.读请求 + 写请求并发
3.更新数据库 + 除缓存的时间 (步 3-4) ,要比读数据库 + 写缓存时间短(步 2 和5)

仔细想一下,条件 3 发生的概率其实是非常低的因为写数据库一般会先[加锁],所以写数据库,通常是要比读数据库的时间更长的这么来看,[先更新数据库 + 再删除缓存]的方案,是可以保证数据一致性的。

所以,我们应该采用这种方案,来操作数据库和缓存

如何保证两步都执行成功?

无论是更新缓存还是删除缓存,只要第二步发生失败,那么就会导致数据库和缓存不一致。
保证第二步成功执行,就是解决问题的关键.

程序在执行过程中发生异常,最简单的解决办法是什么?

答案是:异步重试

  • 如果是同步重试,立即重试很大概率还会失败,[重试次数]设置多少才合理?

  • 重试会一直[占用]这个线程资源,无法服务其它客户端请求

  • 异步其实就是把重试请求写到消息队列中,然后由专门的消费者来重试,直到成功。

为了避免第二步执行失败,我们可以把操作缓存这一步,直接放到消息队列中,由消费者来操作缓存

到这里你可能会问,写消息队列也有可能会失败啊? 而且,引入消息队列,这又增加了更多的维扩成本,这样做值得吗?

这个问题很好,但我们思考这样一个问题:如果在执行失败的线程中一直重试,还没等执行成功,此时如果项目[重启]了,那这次重试请求也就[丢失]了,那这条数据就一直不一致了

所以,这里我们必须把重试消息或第二步操作放到另一个[服务]中,这个服务用[消息队列]最为合适。

  • 消息队列保证可靠性: 写到队列中的消息,成功消费之前不会丢失(重启项目也不担心)
  • 消息队列保证消息成功投递: 下游从队列拉取消息,成功消费后才会删除消息,否则还会继续投递消息给消费者 (符合我们重试的需求)

至于写队列失败和消息队列的维护成本问题

  • 写队列失败: 操作缓存和写消息队列,[同时失败]的概率其实是很小的维护成本:

  • 我们项目中一般都会用到消息队列,维护成本并没有新增很多

参考资料:https://www.zhihu.com/question/319817091
Https://www.jb51.net/database/285448xty.htm
https://baijiahao.baidu.com/s?id=1706150811910444110&wfr=spider&for=pc

来源地址:https://blog.csdn.net/mwq384807683/article/details/132258401

您可能感兴趣的文档:

--结束END--

本文标题: MySQL和Redis如何保证数据一致性

本文链接: https://www.lsjlt.com/news/377998.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL和Redis如何保证数据一致性
    MySQL与Redis都是常用的数据存储和缓存系统。为了提高应用程序的性能和可伸缩性,很多应用程序将MySQL和Redis一起使用,其中MySQL作为主要的持久存储,而Redis作为主要的缓存。在这种情况下,应用程序需要确保MySQL和Re...
    99+
    2023-08-22
    mysql redis 数据库
  • redis和mysql如何保证一致性
    保证 redis 和 mysql 一致性的方法有直接写入 mysql 和事务补偿机制:直接写入 mysql:通过触发器将 mysql 数据变更同步到 redis,保证一致性但性能较低;事...
    99+
    2024-04-20
    mysql redis
  • redis和数据库如何保证一致性
    redis 与数据库之间的数据一致性可以通过以下机制实现:1. 主从复制机制,通过异步复制实现一致性;2. 双写机制,同时向 redis 和数据库写入数据保持同步;3. 乐观锁,通过版本...
    99+
    2024-04-20
    redis 并发访问
  • redis如何保证数据一致性
    Redis 保证数据一致性的方法主要有以下几种: 主从复制:Redis 支持主从复制机制,通过将主节点的数据复制到备用的从节点上...
    99+
    2024-05-10
    redis
  • redis和mysql数据一致性怎么保证
    为了确保 redis 和 mysql 之间的数据一致性,可以采用以下策略:1. 主从复制:利用 mysql 的复制功能,将 mysql 作为主数据库,并将数据同步到 redis 作为从数...
    99+
    2024-04-08
    mysql redis
  • redis如何保证和数据库的一致性
    为了确保 redis 与数据库之间的数据一致性,可使用以下方法:事务性更新:将 redis 和数据库更新封装成原子事务,避免不一致。乐观锁:监视要更新的键,更新前检查键是否已修改,避免并...
    99+
    2024-04-20
    redis
  • MySQL与Redis如何保证数据一致性详解
    前言 由于缓存的高并发和高性能已经在各种项目中被广泛使用,在读取缓存这方面基本都是一致的,大概都是按照下图的流程进行操作: 但是在更新缓存方面,是更新完数据库再更新缓存还是直接删...
    99+
    2024-04-02
  • mysql与redis如何保证数据一致
    MySQL和Redis是两种不同类型的数据库,它们在数据存储和数据处理方面有一些不同之处。在将它们结合使用时,需要考虑如何保证数据一...
    99+
    2024-04-18
    mysql redis
  • Redis 和 MySQL 如何保持数据一致性?
    在高并发的场景下,大量的请求直接访问MySQL很容易造成性能问题。所以,我们都会用Redis来做数据的缓存,削减对数据库的请求。但是,MySQL和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。 一、导致...
    99+
    2023-09-16
    mysql redis
  • redis如何保证缓存和数据库一致性
    redis 通过五种机制维护缓存一致性:1. 写通过缓存,2. 定期同步,3. 事务支持,4. 发布-订阅,5. 校验和修复。选择机制取决于数据变更频率、数据一致性要求、应用性能和维护成...
    99+
    2024-04-20
    redis
  • redis如何保证数据一致
    Redis通过以下方式来保证数据一致性:1. 写操作的原子性:Redis的写操作是原子性的,即对于一个键的写操作要么成功,要么失败,...
    99+
    2023-08-30
    redis
  • redis怎么保证和数据库数据一致性
    Redis是一个内存数据库,通常用作缓存。相比于传统的磁盘数据库,Redis在性能上具有优势,但它也有可能在某些情况下出现数据不一致...
    99+
    2024-02-29
    redis 数据库
  • Java经典面试题:Redis 和 Mysql 如何保证数据一致性
    Redis 和 Mysql 如何保证数据一致性 引言重要性挑战 Redis和MySQL概述Redis(Remote Dictionary Server)MySQL 数据一致性概述Red...
    99+
    2023-10-23
    java redis mysql
  • Redis与MySQL双写一致性如何保证
    🔔什么是双写一致性 指的是当我们更新了数据库的数据之后redis中的数据 也要同步去更新。使用redis读取数据的流程,当用户访问数据的时候,会先从缓存中读取数据,如果命中缓存的话,那...
    99+
    2023-09-13
    redis mysql 缓存
  • Cassandra如何保证数据一致性
    Cassandra 使用了一系列机制来保证数据一致性,包括: 同步复制:Cassandra 采用多节点复制策略,将数据同时复制到...
    99+
    2024-04-09
    Cassandra
  • mysql和redis怎么保证双写一致性
    确保 mysql 和 redis 双写一致性的技术包括:事务性更新:同时更新 mysql 和 redis,保证一致性;主从复制:mysql 主服务器更改同步到 redis 从服务器;基于...
    99+
    2024-04-08
    mysql redis apache
  • redis怎么保证和数据库双写一致性
    为了在redis与数据库双写中保证数据一致性,可以采用以下策略:1. 顺序更新:先写入redis,成功后写入数据库,失败则回滚redis;2. 事务更新:将redis写入和数据库写入作为...
    99+
    2024-04-08
    mysql redis
  • mysql怎么保证数据一致性
    在MySQL中,可以采取以下几种方式来保证数据的一致性:1. 使用事务:事务可以将一系列操作单独的执行单元,要么全部成功提交,要么全...
    99+
    2023-09-15
    mysql
  • 如何保证redis和数据库的双写一致
    为了保持 redis 和数据库双写一致性,可以采取以下措施:1. 使用事务保证操作原子性;2. 使用消息队列解耦写入操作;3. 使用乐观锁保证并发写入原子性;4. 使用主从复制提高可用性...
    99+
    2024-04-19
    redis
  • 怎么保证redis和数据库数据一致
    保证Redis和数据库数据一致性是一个较为复杂的问题,有多种方法可以实现数据一致性。以下是一些常用的方法: 使用事务:在进行数据...
    99+
    2024-04-22
    redis 数据库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作