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

这篇具有很好参考价值的文章主要介绍了如何保障MySQL和Redis的数据一致性?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

 文章来源地址https://www.toymoban.com/news/detail-710932.html

 

不好的方案

 

1、先写 MySQL,再写 Redis

 

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

 

 

如图所示:

 

  • 这是一副时序图,描述请求的先后调用顺序;

 

  • 橘黄色的线是请求 A,黑色的线是请求 B;

 

  • 橘黄色的文字,是 MySQL 和 Redis 最终不一致的数据;

 

  • 数据是从 10 更新为 11;

 

  • 后面所有的图,都是这个含义,不再赘述。

 

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

 

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

 

2、先写 Redis,再写 MySQL

 

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

 

 

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

 

3、先删除 Redis,再写 MySQL

 

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

 

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

 

 

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

 

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

 

好的方案

 

1、先删除 Redis,再写 MySQL,再删除 Redis

 

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

 

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

 

 

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

 

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

 

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

 

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

 

 

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

 

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

 

简单小结一下:

 

  • “缓存双删”不要用无脑的 sleep 500 ms;

 

  • 通过消息队列的异步&串行,实现最后一次缓存删除;

 

  • 缓存删除失败,增加重试机制。

 

2、先写 MySQL,再删除 Redis

 

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

 

 

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

 

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

 

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

 

 

这里需要满足 2 个条件:

 

  • 缓存刚好自动失效;

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

 

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

 

3、先写 MySQL,通过 Binlog,异步更新 Redis

 

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

 

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

 

 

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

 

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

 

几种方案比较

 

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

 

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,是最终一致性的最优解。

 

作者丨楼仔

到了这里,关于如何保障MySQL和Redis的数据一致性?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    如果对于小公司的单机服务器来说在更新和删除mysql数据的同时对redis缓存进行更新或者删除就行,一般有两个选择,例如: 先更新MySQL,后删除(或更新)Redis 先删除(或更新)Redis,后更新MySQL 但是不管使用其中哪种方式,都存在两个可能的问题: 由于第一步与第二步并不是原

    2023年04月24日
    浏览(52)
  • Redis缓存MySQL数据库存储二者如何保证数据一致性

    在大型互联网应用中,由于数据库读写频繁、压力大等原因,我们通常会使用缓存来减少数据库的访问次数,提高系统的性能。而Redis作为一个高性能的内存数据库,成为了缓存的首选方案之一。但是,缓存和数据库之间存在数据一致性的问题,如何解决这个问题呢?本文将

    2023年04月19日
    浏览(52)
  • MySQL 和 Redis 如何保证数据一致性,通过MySQL的binlog实现

    1、简介         MySQL 和 Redis 如何保证数据一致性,目前大多讨论的是先更新Redis后更新MySQL,还是先更新MySQL 后更新Redis,这两种方式在实际的应用场景中都不能确保数据的完全一致性,在某些情况下会出现问题,本文介绍使用 Canal 工具,通过将自己伪装成MySQL的从节点,读

    2024年02月02日
    浏览(59)
  • Redis与MySQL双写一致性如何保证

    前言 在分布式系统中,数据一致性是一个重要的问题。当我们使用Redis和MySQL这两种不同的数据库时,如何保证它们之间的双写一致性是一个需要解决的难题。本文将探讨Redis与MySQL双写一致性的保证方法。 什么是双写一致性? 指的是当我们更新了数据库的数据之后redis中的数

    2024年02月09日
    浏览(44)
  • 生产实践:Redis与Mysql的数据强一致性方案

    数据库和Redis如何保持强一致性,这篇文章告诉你 Redis和Msql来保持数据同步,并且强一致,以此来提高对应接口的响应速度,刚开始考虑是用mybatis的二级缓存,发现坑不少,于是决定自己搞 操作数据必须是唯一索引 如果更新数据不是唯一索引,则数据库更新后的值,与缓存

    2024年02月05日
    浏览(55)
  • MySQL与Redis数据双写一致性工程落地案例

    多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。 其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。 后面的线程进来发现已经有缓存了,就直接走缓存。   canal [kə\\\'næl],中文翻译

    2024年02月03日
    浏览(92)
  • 04_Redis与mysql数据双写一致性案例

    是什么 canal[ka’nel,中文翻译为水道/管道/沟渠/运河,主要用途是用于MySQL数据库增量日志数据的订阅、消费和解析,是阿里巴巴开发并开源的,采用Java语言开发; 历史背景是早期阿里巴巴因为杭州和美国双机房部署,存在跨机房数据同步的业务需求,实现方式主要是基野业务

    2024年02月12日
    浏览(38)
  • Redis如何保证缓存和数据库一致性?

    现在我们在面向增删改查开发时,数据库数据量大时或者对响应要求较快,我们就需要用到Redis来拿取数据。 Redis:是一种高性能的内存数据库,它将数据以键值对的形式存储在内存中,具有读写速度快、支持多种数据类型、原子性操作、丰富的特性等优势。 优势: 性能极高

    2024年01月16日
    浏览(70)
  • Redis---数据库和缓存如何保证一致性?

    用「读 + 写」请求的并发的场景来分析: 假如某个用户数据在缓存中不存在,请求 A 读取数据时从数据库中查询到年龄为 20,在未写入缓存中时另一个请求 B 更新数据。它更新数据库中的年龄为 21,并且清空缓存。这时请求 A 把从数据库中读到的年龄为 20 的数据写入到缓存

    2024年01月24日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包