如何保证redis与db的双写一致性

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

引言

    如何保证redis与db的双写一致性?这是一个十分热门的面试话题。 如何理解“一致性”这个概念?“事务”中“一致性”的定义是: 事务执行前后,数据从一个合法性状态变换到另外一个合法性状态。  比喻说,更新前:redis中记录的是100,db中记录的也是100。更新后: redis中记录的是 80,db中记录的也是 80。 

一、问题场景假设

在同时更新redis和db时,可能出现更新某一个失败或者更新不及时,导致双写一致性问题。

比喻说,更新前:redis中记录的是100,db中记录的也是100

二、基本原则

1、数据必须优先落库db。redis只是db的数据缓存。

2、做更新操作时,数据必须以db的为主。不能以redis查询的数据,去做计算再更新db。

3.  更新db时,为了保障隔离性。需要加锁(基于版本号的乐观锁或者for update悲观锁)

4.  查询时先查询redis,如果redis未命中,则继续查db。再把查询结果写回redis

三、可能的解决办法

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

问题一:更新redis成功+更新db失败。

案例更新结果: redis中记录的是 80,db中记录的也是 100

不可取。除了没有保障一致性,而且违背了原则1

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

问题一:更新db成功+更新redis失败

案例更新结果: redis中记录的是 100,db中记录的也是 80。

问题二:更新db成功+更新redis不及时

正常情况:

  1.  线程A更新db为80
  2.  线程A更新redis为80
  3.  线程B更新db为90
  4.  线程B更新redis为90

异常情况1

  1.   线程A更新db为80
  2.   线程B更新db为90
  3.   线程B更新redis为90
  4.   线程A更新redis为80

案例更新结果: redis中记录的是 90,db中记录的也是 80。

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

问题一:删除redis成功+更新db延迟

异常情况2

  1. 线程A删除redis缓存
  2. 线程A更新DB为80。执行完需要5秒
  3. 线程B在A更新DB第1秒开始执行查询。查询redis没命中,再查询db为100,再更新redis为100

案例更新结果: redis中记录的是 100,db中记录的也是 80。

4.延迟双删(先删除redis,再更新db,再删除redis)

延迟双删,可以解决异常情况2

异常情况3:

  1. 线程A删除redis缓存成功
  2. 线程A更新db为80。执行完需要5秒
  3. 线程B在A更新DB第1秒开始执行查询。查询redis没命中,再查询db为100,再更新redis为100
  4. 线程A删除redis失败。redis宕机了。

为了解决第二次删除redis可能失败,可以使用消息队列或者canel订阅mysql的binlog日志等实现延迟删除 + 失败补偿

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

问题一:更新db成功+删除redis失败

异常情况

  1. 线程A更新DB为80
  2. 线程A删除redis失败
  3. 线程B执行查询。先查询redis,命中返回结果100

案例更新结果: redis中记录的是 100,db中记录的也是 80。

四、推荐解决方案

技术选型:

   mysql + rabbitmq + canel + redis

1.redis采用集群,实现高可用。

2.查询。先查询redis。未命中,则DCL(双检锁) 的方式,查询db。查询结果再写入redis

3.更新。

     3.1 更新db时,需要加锁。如加for update悲观锁,或者基于版本号的乐观锁。(防止多线程同时更新,相互影响)

     3.2 更新db时,set的字段取值,不能使用redis查询的结果,必须使用db的查询结果(避免读到redis的脏数据,而db如mysql的默认隔离级别是可重复读,不会读到脏数据

     3.3  更新顺序。必须优先保障数据落库db。可以分为:

        3.3.1   延迟双删(先删除redis, 再更新db,最后再删除redis)。

               在落地时,为了防止第二次删除redis失败,可以通过以下两种方案:

           3.3.1.1  基于消息队列

              在准备第二次删除redis缓存时,将其放入消息队列。消息队列消费失败,放入死信队列。预设死信队列失败重试次数。死信队列消费次数超过阈值,则日志报警。(消息队列也要搭建集群来保障可用性)

          3.3.1.2   canel订阅mysql的binlog日志

              通过阿里的canel中间件来订阅mysql的binlog日志,来实现异步删除。删除失败,则放入消息队列。

        3.3.2   先更新db,再删除redis。

              先删除db,然后删除redis。如果删除redis失败,则放入消息队列。消息队列消费失败,则放入私信队列。

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

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

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

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

相关文章

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

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

    2024年02月12日
    浏览(62)
  • MySQL和Redis如何保证数据一致性?

    由于缓存的高并发和高性能已经在各种项目中被广泛使用,在读取缓存这方面基本都是一致的,大概都是按照下图的流程进行操作: 但是在更新缓存方面,是更新完数据库再更新缓存还是直接删除缓存呢?又或者是先删除缓存再更新数据库?在这一点上就值得探讨了。 在实

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

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

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

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

    2024年01月24日
    浏览(57)
  • Redis双写一致性?

    双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致。 Redis作为缓存,mysql的数据如何与redis进行同步呢?(双写一致性) 1.我们当时做排行榜业务时,把历史榜单数据存储到了缓存中。这个虽然也是热点数据,但是实时要求性不高。

    2024年02月16日
    浏览(45)
  • mysql和redis如何保证数据库一致性

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

    2023年04月24日
    浏览(52)
  • 如何保证Redis缓存和数据库的一致性问题

    熟练掌握Redis缓存技术? 那么请问Redis缓存中有几种读写策略,又是如何保证与数据库的一致性问题 今天来聊一聊常用的三种缓存读写策略 首先我们来思考一个问题 写 先更新缓存 再更新数据库 首先如果缓存更新成功但数据库更新失败,会导致数据不一致的问题 其次当请求

    2024年02月14日
    浏览(51)
  • Redis---缓存双写一致性

    目录 一、什么是缓存双写一致性呢?  1.1 双检加锁机制  二、数据库和缓存一致性的更新策略 2.1、先更新数据库,后更新缓存  2.2 、先更新缓存,后更新数据库  2.3、先删除缓存,在更新数据库 延时双删的策略:  2.4.先更新数据库,在删除缓存(常用) 2.5、实际中是不可

    2024年02月15日
    浏览(49)
  • Redis缓存(双写一致性问题)

    前言 : 什么是缓存? 缓存就像自行车,越野车的避震器 举个例子:越野车,山地自行车,都拥有\\\"避震器\\\", 防止 车体加速后因惯性,在酷似\\\"U\\\"字母的地形上飞跃,硬着陆导致的 损害 ,像个弹簧一样; 同样,实际开发中,系统也需要\\\"避震器\\\",防止过高的数据访问猛冲系统,导致其操作线程无法

    2024年02月02日
    浏览(64)
  • Redis缓存双写一致性

    如果redis中有数据:需要和数据库中的值相同 如果redis中无数据:数据库中的值要是最新值,且准备回写redis 缓存按照操作来分,可细分为两种: 只读缓存和读写缓存 只读缓存很简单:就是Redis只做查询,有就是有,没有就是没有,不会再进一步访问MySQL,不再需要会写机制

    2023年04月17日
    浏览(46)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包