我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

​大家好,我是楼仔!

这个问题很早之前我就遇到过,但是一直没有仔细去研究,上个月看了极客的课程,有一篇文章专门有过讲解,刚好有粉丝也问我这个问题,所以感觉有必要单独出一篇。

之前也看了很多相关的文章,但是感觉讲的都不好,很多文章都会去讲各种策略,比如(旁路缓存)策略、(读穿 / 写穿)策略和(写回)策略等,感觉意义真的不大,然后有的文章也只讲了部分情况,也没有告诉最优解。

我直接先抛一下结论:在满足实时性的条件下,不存在两者完全保存一致的方案,只有最终一致性方案。 根据网上的众多解决方案,总结出六种,直接看目录:

不好的方案

1. 先写 MySQL,再写 Redis

图解说明:

  • 这是一副时序图,描述请求的先后调用顺序;
  • 橘黄色的线是请求 A,黑色的线是请求 B;
  • 橘黄色的文字,是 MySQL 和 Redis 最终不一致的数据;
  • 数据是从 10 更新为 11;
  • 后面所有的图,都是这个含义,不再赘述。

请求 A、B 都是先写 MySQL,然后再写 Redis,在高并发情况下,如果请求 A 在写 Redis 时卡了一会,请求 B 已经依次完成数据的更新,就会出现图中的问题。

这个图已经画的很清晰了,我就不用再去啰嗦了吧,不过这里有个前提,就是对于读请求,先去读 Redis,如果没有,再去读 DB,但是读请求不会再回写 Redis。 大白话说一下,就是读请求不会更新 Redis。

2. 先写 Redis,再写 MySQL

同“先写 MySQL,再写 Redis”,看图可秒懂。

3. 先删除 Redis,再写 MySQL

这幅图和上面有些不一样,前面的请求 A 和 B 都是更新请求,这里的请求 A 是更新请求,但是请求 B 是读请求,且请求 B 的读请求会回写 Redis。

请求 A 先删除缓存,可能因为卡顿,数据一直没有更新到 MySQL,导致两者数据不一致。

这种情况出现的概率比较大,因为请求 A 更新 MySQL 可能耗时会比较长,而请求 B 的前两步都是查询,会非常快。

好的方案

4. 先删除 Redis,再写 MySQL,再删除 Redis

对于“先删除 Redis,再写 MySQL”,如果要解决最后的不一致问题,其实再对 Redis 重新删除即可,这个也是大家常说的“缓存双删”。

为了便于大家看图,对于蓝色的文字,“删除缓存 10”必须在“回写缓存10”后面,那如何才能保证一定是在后面呢?网上给出的第一个方案是,让请求 A 的最后一次删除,等待 500ms。

对于这种方案,看看就行,反正我是不会用,太 Low 了,风险也不可控。

那有没有更好的方案呢,我建议异步串行化删除,即删除请求入队列:

异步删除对线上业务无影响,串行化处理保障并发情况下正确删除。

如果双删失败怎么办,网上有给 Redis 加一个缓存过期时间的方案,这个不敢苟同。个人建议整个重试机制,可以借助消息队列的重试机制,也可以自己整个表,记录重试次数,方法很多。

简单小结一下:

  • “缓存双删”不要用无脑的 sleep 500 ms;
  • 通过消息队列的异步&串行,实现最后一次缓存删除;
  • 缓存删除失败,增加重试机制。

5. 先写 MySQL,再删除 Redis

对于上面这种情况,对于第一次查询,请求 B 查询的数据是 10,但是 MySQL 的数据是 11,只存在这一次不一致的情况,对于不是强一致性要求的业务,可以容忍。(那什么情况下不能容忍呢,比如秒杀业务、库存服务等。)

当请求 B 进行第二次查询时,因为没有命中 Redis,会重新查一次 DB,然后再回写到 Reids。

这里需要满足 2 个条件:

  • 缓存刚好自动失效;
  • 请求 B 从数据库查出 10,回写缓存的耗时,比请求 A 写数据库,并且删除缓存的还长。

对于第二个条件,我们都知道更新 DB 肯定比查询耗时要长,所以出现这个情况的概率很小,同时满足上述条件的情况更小。

6. 先写 MySQL,通过 Binlog,异步更新 Redis

这种方案,主要是监听 MySQL 的 Binlog,然后通过异步的方式,将数据更新到 Redis,这种方案有个前提,查询的请求,不会回写 Redis。

这个方案,会保证 MySQL 和 Redis 的最终一致性,但是如果中途请求 B 需要查询数据,如果缓存无数据,就直接查 DB;如果缓存有数据,查询的数据也会存在不一致的情况。

所以这个方案,是实现最终一致性的终极解决方案,但是不能保证实时性。

几种方案比较

我们对比上面讨论的六种方案:

(1) 先写 Redis,再写 MySQL

  • 这种方案,我肯定不会用,万一 DB 挂了,你把数据写到缓存,DB 无数据,这个是灾难性的;
  • 我之前也见同学这么用过,如果写 DB 失败,对 Redis 进行逆操作,那如果逆操作失败呢,是不是还要搞个重试?

(2) 先写 MySQL,再写 Redis

  • 对于并发量、一致性要求不高的项目,很多就是这么用的,我之前也经常这么搞,但是不建议这么做;
  • 当 Redis 瞬间不可用的情况,需要报警出来,然后线下处理。

(3) 先删除 Redis,再写 MySQL

  • 这种方式,我还真没用过,直接忽略吧。

(4) 先删除 Redis,再写 MySQL,再删除 Redis

  • 这种方式虽然可行,但是感觉好复杂,还要搞个消息队列去异步删除 Redis。

(5) 先写 MySQL,再删除 Redis

  • 比较推荐这种方式,删除 Redis 如果失败,可以再多重试几次,否则报警出来;
  • 这个方案,是实时性中最好的方案,在一些高并发场景中,推荐这种。

(6) 先写 MySQL,通过 Binlog,异步更新 Redis

  • 对于异地容灾、数据汇总等,建议会用这种方式,比如 binlog + kafka,数据的一致性也可以达到秒级;
  • 纯粹的高并发场景,不建议用这种方案,比如抢购、秒杀等。

个人结论

  • 实时一致性方案:采用“先写 MySQL,再删除 Redis”的策略,这种情况虽然也会存在两者不一致,但是需要满足的条件有点苛刻,所以是满足实时性条件下,能尽量满足一致性的最优解。
  • 最终一致性方案:采用“先写 MySQL,通过 Binlog,异步更新 Redis”,可以通过 Binlog,结合消息队列异步更新 Redis,是最终一致性的最优解。​​​

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

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

下载Word文档

猜你喜欢

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

在满足实时性的条件下,MySQL 和 Redis 不存在两者完全保存一致的方案,只有最终一致性方案。

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

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

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

启动一个订阅程序去订阅数据库的binlog,获得需要操作的数据。在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作。

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

今天给大家剖析一下工作中常见的 MySQL 和 Redis 数据一致性问题。

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

Mysql和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。

如何保障redis缓存和mysql数据相一致

如何保障 redis 缓存与 mysql 数据一致性?异步更新:通过消息队列进行更新,不阻塞应用程序。定期同步:使用定时作业定期同步数据,保持数据一致性。混合方法:结合异步和定期同步,兼顾效率和一致性。缓存失效:更新 mysql 数据时使
如何保障redis缓存和mysql数据相一致
2024-04-19

redis和mysql如何保证一致性

保证 redis 和 mysql 一致性的方法有直接写入 mysql 和事务补偿机制:直接写入 mysql:通过触发器将 mysql 数据变更同步到 redis,保证一致性但性能较低;事务补偿机制:先写入 redis,同时记录补偿事务,容忍
redis和mysql如何保证一致性
2024-04-20

redis如何保证和数据库的一致性

为了确保 redis 与数据库之间的数据一致性,可使用以下方法:事务性更新:将 redis 和数据库更新封装成原子事务,避免不一致。乐观锁:监视要更新的键,更新前检查键是否已修改,避免并发冲突。发布-订阅:使用 redis 频道发布消息,订
redis如何保证和数据库的一致性
2024-04-20

redis和数据库如何保证一致性

redis 与数据库之间的数据一致性可以通过以下机制实现:1. 主从复制机制,通过异步复制实现一致性;2. 双写机制,同时向 redis 和数据库写入数据保持同步;3. 乐观锁,通过版本号或时间戳控制并发访问保证一致性;4. 事务补偿机制,
redis和数据库如何保证一致性
2024-04-20

MySQL数据一致性保障

MySQL通过一系列机制来确保数据的一致性,主要包括事务管理、锁机制、日志(如redo log和binlog)以及两阶段提交等。以下是MySQL数据一致性保障的相关信息:MySQL数据一致性保障机制事务管理:MySQL通过事务管理确保数据
MySQL数据一致性保障
2024-10-20

redis和mysql数据一致性怎么保证

为了确保 redis 和 mysql 之间的数据一致性,可以采用以下策略:1. 主从复制:利用 mysql 的复制功能,将 mysql 作为主数据库,并将数据同步到 redis 作为从数据库。2. 事务队列:将更新请求发送到事务队列,由消费
redis和mysql数据一致性怎么保证
2024-04-08

redis如何保证数据一致性

Redis 保证数据一致性的方法主要有以下几种:主从复制:Redis 支持主从复制机制,通过将主节点的数据复制到备用的从节点上,保证数据的一致性。当主节点发生故障时,从节点可以顶替主节点继续提供服务。数据持久化:Redis 支持将内存中的数
redis如何保证数据一致性
2024-05-10

redis如何保证缓存和数据库一致性

redis 通过五种机制维护缓存一致性:1. 写通过缓存,2. 定期同步,3. 事务支持,4. 发布-订阅,5. 校验和修复。选择机制取决于数据变更频率、数据一致性要求、应用性能和维护成本等因素。Redis如何实现缓存一致性Redis作为
redis如何保证缓存和数据库一致性
2024-04-20

ORM与MySQL的数据一致性保障

ORM(对象关系映射)框架通过将数据库表映射为对象,简化了应用程序与数据库之间的交互。然而,数据一致性是数据库操作中的一个关键问题,需要特别关注。以下是关于ORM与MySQL的数据一致性保障的相关信息:MySQL的数据一致性保障事务管理:
ORM与MySQL的数据一致性保障
2024-10-05

mysql与redis如何保证数据一致

MySQL和Redis是两种不同类型的数据库,它们在数据存储和数据处理方面有一些不同之处。在将它们结合使用时,需要考虑如何保证数据一致性。一种常见的方法是使用事务来确保数据的一致性。在MySQL中,可以使用事务来保证数据库操作的原子性、一
mysql与redis如何保证数据一致
2024-04-18

Redis做为缓存,MySQL如何与Redis保持数据一致性?

一般情况下Redis是用来实现应用和数据库之间的一个读操作的缓存层,主要目的是减少数据库的io,还可以提升数据库io性能
Redis数据库2024-11-30

热门标签

编程热搜

编程资源站

目录