mysql和redis数据如何保持一致

京东云官方 京东云官方     2022-12-01     513

关键词:

先阐明一下Mysql和Redis的关系:Mysql是数据库,用来持久化数据,一定程度上保证数据的可靠性;Redis是用来当缓存,用来提升数据访问的性能。

关于如何保证Mysql和Redis中的数据一致(即缓存一致性问题),这是一个非常经典的问题。

使用过缓存的人都应该知道,在实际应用场景中,要想实时刻保证缓存和数据库中的数据一样,很难做到。

基本上都是尽可能让他们的数据在绝大部分时间内保持一致,并保证最终是一致的。

缓存不一致是如何产生的

如果数据一直没有变更,那么就不会出现缓存不一致的问题。

通常缓存不一致是发生在数据有变更的时候。 因为每次数据变更你需要同时操作数据库和缓存,而他们又属于不同的系统,无法做到同时操作成功或失败,总会有一个时间差。在并发读写的时候可能就会出现缓存不一致的问题(理论上通过分布式事务可以保证这一点,不过实际上基本上很少有人这么做)。

虽然没办法在数据有变更时,保证缓存和数据库强一致,但对缓存的更新还是有一定设计方法的,遵循这些设计方法,能够让这个不一致的影响时间和影响范围最小化。

缓存更新的几种设计

缓存更新的设计方法大概有以下四种:

  • 先删除缓存,再更新数据库(这种方法在并发下最容易出现长时间的脏数据,不可取)
  • 先更新数据库,删除缓存(Cache Aside Pattern)
  • 只更新缓存,由缓存自己同步更新数据库(Read/Write Through Pattern)
  • 只更新缓存,由缓存自己异步更新数据库(Write Behind Cache Pattern)

接下来详细介绍一些这四种设计方法

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

这种方法在并发读写的情况下容易出现缓存不一致的问题

Mysql和Redis数据如何保持一致_数据库

如上图所示,其可能的执行流程顺序为:

  • 客户端1 触发更新数据A的逻辑
  • 客户端2 触发查询数据A的逻辑
  • 客户端1 删除缓存中数据A
  • 客户端2 查询缓存中数据A,未命中
  • 客户端2 从数据库查询数据A,并更新到缓存中
  • 客户端1 更新数据库中数据A

可见,最后缓存中的数据A跟数据库中的数据A是不一致的,缓存中的数据A是旧的脏数据。

因此一般不建议使用这种方式。

先更新数据库,再让缓存失效

这种方法在并发读写的情况下,也可能会出现短暂缓存不一致的问题

Mysql和Redis数据如何保持一致_缓存_02

如上图所示,其可能执行的流程顺序为:

  • 客户端1 触发更新数据A的逻辑
  • 客户端2 触发查询数据A的逻辑
  • 客户端3 触发查询数据A的逻辑
  • 客户端1 更新数据库中数据A
  • 客户端2 查询缓存中数据A,命中返回(旧数据)
  • 客户端1 让缓存中数据A失效
  • 客户端3 查询缓存中数据A,未命中
  • 客户端3 查询数据库中数据A,并更新到缓存中

可见,最后缓存中的数据A和数据库中的数据A是一致的,理论上可能会出现一小段时间数据不一致,不过这种概率也比较低,大部分的业务也不会有太大的问题。

只更新缓存,由缓存自己同步更新数据库(Read/Write Through Pattern)

这种方法相当于是业务只更新缓存,再由缓存去同步更新数据库。 一个Write Through的 例子如下:

Mysql和Redis数据如何保持一致_数据_03

如上图所示,其可能执行的流程顺序为:

  • 客户端1 触发更新数据A的逻辑
  • 客户端2 触发查询数据A的逻辑
  • 客户端1 更新缓存中数据A,缓存同步更新数据库中数据A,再返回结果
  • 客户端2 查询缓存中数据A,命中返回

Read Through 和 WriteThrough 的流程类似,只是在客户端查询数据A时,如果缓存中数据A失效了(过期或被驱逐淘汰),则缓存会同步去数据库中查询数据A,并缓存起来,再返回给客户端

这种方式缓存不一致的概率极低,只不过需要对缓存进行专门的改造。

只更新缓存,由缓存自己异步更新数据库(Write Behind Cache Pattern)

这种方式性详单于是业务只操作更新缓存,再由缓存异步去更新数据库,例如:

Mysql和Redis数据如何保持一致_mysql_04

如上图所示,其可能的执行流程顺序为:

  • 客户端1 触发更新数据A的逻辑
  • 客户端2 触发查询数据A的逻辑
  • 客户端1 更新缓存中的数据A,返回
  • 客户端2 查询缓存中的数据A,命中返回
  • 缓存异步更新数据A到数据库中

这种方式的优势是读写的性能都非常好,基本上只要操作完内存后就返回给客户端了,但是其是非强一致性,存在丢失数据的情况。

如果在缓存异步将数据更新到数据库中时,缓存服务挂了,此时未更新到数据库中的数据就丢失了。

总结

上面讲到的几种缓存更新的设计方式,都是前人总结出来的经验,这些方式或多或少都有一些弊端,并不完美,实际上也很难有完美的设计。 大家在做系统设计的时候,也不要去追求完美,要有一些取舍,找到一种最适合自己业务场景的方式就行

作者:追光者

redis和mysql数据不一致问题如何解决?

阅读目录解决思路解决方法方法1:数据实时更新方法2:数据准实时更新方法3:缓存失效机制方法4:定时任务更新解决思路要解决缓存数据不一致的问题,首先要理解为什么缓存和数据库会存在不一致的情况。什么情况下缓存... 查看详情

如何保证mysql和redis的数据一致性?10张图带你搞定!

...语 | 本文的主要思路是首先带大家认识了解MySQL和Redis的数据一致性情况,然后进行反推不一致的情况,从而进行探究单线程中的不一致的情况。同时探究多线程中的不一致的情况,拟定数据一致性策略。一、什么是... 查看详情

美团二面:redis与mysql双写一致性如何保证?(代码片段)

...ySQL双写一致性如何保证?这道题其实就是在问缓存和数据库在双写场景下,一致性是如何保证的?本文将跟大家一起来探讨如何回答这个问题。公众号:捡田螺的小男孩谈谈一致性一致性就是数据保持一致,... 查看详情

redisutils工具类,设置缓存,然后需要在删除,更新插入的时候清空缓存,保持redis和mysql的数据一致(代码片段)

...目录1.查询的时候先查询缓存,如果为空就会以查询数据库,然后设置值到缓存2.在进行修改(insert,delete,update)操作的时候进行删除缓存(这样就会下次查询的时候缓存为空,又会重新设置缓存)3.缓存工具类1.... 查看详情

redisutils工具类,设置缓存,然后需要在删除,更新插入的时候清空缓存,保持redis和mysql的数据一致(代码片段)

...目录1.查询的时候先查询缓存,如果为空就会以查询数据库,然后设置值到缓存2.在进行修改(insert,delete,update)操作的时候进行删除缓存(这样就会下次查询的时候缓存为空,又会重新设置缓存)3.缓存工具类1.... 查看详情

redis缓存如何保证一致性

为什么使用Redis做缓存MySQL缺点单机连接数目有限对数据进行写速度慢Redis优点内存操作数据速度快IO复用,速度快单线程模型,避免线程切换带来的开销,速度快一致性问题  读数据的时候首先去Redis里读,没有读到再去MySQL里... 查看详情

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

...请求B;橘黄色的文字,是MySQL和Redis最终不一致的数据;数据是从10更新为11;后面所有的图,都是这个含义,不再赘述。请求A、B都是先写MySQL,然后再写Redis,在高并发情况下,如果请求A在写Re... 查看详情

oracle和sql如何保持表数据一致

】oracle和sql如何保持表数据一致【英文标题】:howtokeeptabledatasameinoracleandsql【发布时间】:2012-05-3104:16:09【问题描述】:我正在尝试在sqlserver中构建一个数据库,以复制oracle生产数据库中表中存在的确切数据。sqlserver中的数据库... 查看详情

认识mysql和redis的数据一致性问题(代码片段)

作者:sinxu,腾讯CSIG后台开发工程师,写入数据库;访问数据时,缓存缺失,查数据库,更新缓存(始终是处于”数据一致“的状态,不会发生数据不一致性问题)更新(修改/删除)数据时,会有个时序问题:更新数据库与删除... 查看详情

认识mysql和redis的数据一致性问题

作者:sinxu,腾讯CSIG后台开发工程师1.什么是数据的一致性“数据一致”一般指的是:缓存中有数据,缓存的数据值=数据库中的值。但根据缓存中是有数据为依据,则”一致“可以包含两种情况:缓存... 查看详情

美团2面:如何保障mysql和redis数据一致性?这样答,让面试官爱到死去活来

美团2面:如何保障MySQL和Redis的数据一致性?说在前面在尼恩的(50+)读者社群中,经常遇到一个非常、非常高频的一个面试题,但是很不好回答,类似如下:如何保障MySQL和Redis的数据一致性... 查看详情

最终与数据库和消息队列记录保持一致

】最终与数据库和消息队列记录保持一致【英文标题】:Eventualconsistencywithbothdatabaseandmessagequeuerecords【发布时间】:2017-06-2213:19:19【问题描述】:我有一个应用程序,我需要在数据库中存储一些数据(例如mysql),然后在消息队... 查看详情

如何对多个 mysql foreach 数组进行排序并需要它们在 php 中保持一致?

...05-0809:33:53【问题描述】:我正在尝试按我的计算值对mysql数据进行排序。我知道rsort(),sort(),但是,我不能在foreach之外对它们进行单独排序,因为它不会是一致 查看详情

redis┃面试官问我redis事务和mysql事务的区别,我

...我:学到了。。。。。。2、正文事务的四大特性ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。说的是一个事物内所有操作就是最... 查看详情

redis与mysql双写一致性(代码片段)

双写一致性时为了保证Redis缓存与MySQL数据库中的数据一样我们对Redis中没有的数据,MySQL怎么回写呢?我们用双检加锁策略这样只要第一个请求发过来,后面的请求就不会发送到MySQL,直接从Redis中获取缓存数据就可以了。 为... 查看详情

在 Firebase 数据库中,当需要推送和更新操作时,如何保持数据一致性?

】在Firebase数据库中,当需要推送和更新操作时,如何保持数据一致性?【英文标题】:InFirebasedatabase,howtokeepdataconsistencywhenbothpushandupdateoperationsareneeded?【发布时间】:2018-04-0900:37:41【问题描述】:假设我在Firebase中有以下数据... 查看详情

与程序保持一致的 Python 数据库

】与程序保持一致的Python数据库【英文标题】:PythonDatabasethatstayswiththeprogram【发布时间】:2020-09-1923:56:07【问题描述】:因此,当您在该设备上登录mysql数据库程序时,mysql工作得很好,但是如果您想将程序移动到另一台设备上... 查看详情

redis缓存测试

...么要使用缓存?当然是为了快和省。快是因为业务系统的数据处理结果暂时存在内存中,下次访问时直接从内存取出,所以会很快。省是节省数据的处理流程及服务器的资源消耗。所以,什么时候使用缓存呢?当业务出现性能瓶... 查看详情