Redis缓存双写一致性

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

1、缓存双写一致性的理解

Redis缓存双写一致性
如果redis中有数据:需要和数据库中的值相同
如果redis中无数据:数据库中的值要是最新值,且准备回写redis

缓存按照操作来分,可细分为两种:只读缓存和读写缓存

只读缓存很简单:就是Redis只做查询,有就是有,没有就是没有,不会再进一步访问MySQL,不再需要会写机制

大部分都是读写缓存,又分为两种:
同步直写策略
写数据库后也同步写redis缓存,缓存和数据库中的数据一 致
对于读写缓存来说,要想保证缓存和数据库中的数据一致,就要采用同步直写策略
比如特别重要的数据、热点敏感数据,例如充值后就需要立马更新,及时生效

异步缓写策略
正常业务运行中,mysq|数据变动了,但是可以在业务上容许出现一定时间后才作用于redis,比如仓库、物流系统、积分变更
异常情况出现了,不得不将失败的动作重新修补,有可能需要借助kafka或者RabbitMQ等消息中间件,实现重试重写
Redis缓存双写一致性

业务流程写得没错,对于QPS(每秒查询率)小于1000可以使用,但是对于高并发场景不适于。比如在高并发场景下,许多线程几乎同时(时间间隔得不那么开)查询相同的值,由于redis中没有,会全部直接打到MySQL上,MySQL可能就会被打宕机,即使没宕机,这些线程又会进行大量的回写,而且回写的还是同一个值。这里的本质就是:查询MySQL和回写不是原子操作。

对于上述情况,需要采用双检测加锁策略,类似于单例模式中的懒汉模式(可以采用双检测加锁策略实现)

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

Redis缓存双写一致性

2、数据库和缓存一致性的几种更新策略

目的:无论怎么操作,我们要达到最终一致性

给缓存设置过期时间,定期清理缓存并回写,是保证最终一致性的解决方案。
我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存,达到一致性,切记,要以mysql的数据库写入库为准。

可以停机的情况下
挂牌报错,凌晨升级,温馨提示,服务降级
单线程,这样重量级的数据操作最好不要多线程

不可以停机的情况,则有4种更新策略

2.1 先更新数据库,再更新缓存

异常问题1:

  1. 先更新mysql的某商品的库存,当前商品的库存是100,更新为99个
  2. 先更新mysq|修改为99成功,然后更新redis
  3. 此时假设异常出现,更新redis失败了,这导致mysq|里面的库存是99而redis里面的还是100
  4. 上述发生,会让数据库里面和缓存redis里面数据不一致,读到redis脏数据

例如:正当需要更新redis的数据时,此时可能master主机宕机,salve正在处于上位(成为新的master)的过程,没时间来回应更新redis的数据,或者更新redis的操作丢失,这就会导致mysql更新成功,redis更新失败,后续所有读操作都读到了脏数据

异常问题2:

A、B两个线程同时发起调用(实际上可能会存在更多的线程)
正常逻辑

  1. 线程A更新mysql中的某个值,例如a,更新为100
  2. 线程A更新redis中的a为100
  3. 线程B更新mysql中的a,更新为80
  4. 线程B更新redis中的a为80

异常逻辑
多线程环境下,A、B两个线程有快有慢,有前有后有并行

  1. 线程A更新mysql中的a,更新为100
  2. 线程B更新mysql中的a,更新为80
  3. 线程B更新完mysql,立刻回写更新redis中的a为80
  4. 线程A更新redis中的a为100

最终结果,mysq|和redis数据不一 致

2.2 先更新缓存,再更新数据库

从技术上可以做,但不太推荐,业务上一般把mysq|作为底单数据库,保证最后解释

异常问题

正常逻辑
A、B两个线程同时发起调用(实际上可能会存在更多的线程)

  1. 线程A更新redis中的a为100
  2. 线程A更新mysql中的a为100
  3. 线程B更新redis中的a为80
  4. 线程B更新mysql中的a为80

异常逻辑
多线程环境下,A、B两个线程有快有慢,有前有后有并行

  1. 线程A更新redis中的a为100
  2. 线程B更新redis中的a为80
  3. 线程B更新redis中的a为80
  4. 线程A更新mysql中的a为100

最终结果,mysq|和redis数据不一 致

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

异常问题,先删除缓存,再更新数据库(不进行回写),等到再次查询时,才进行回写操作

  1. A线程先成功删除了redis里面的数据,然后去更新mysq|,此时mysq|正在更新中,还没有结束(比如网路延时,或者还没有commit)
  2. 线程B突然要来读取redis缓存数据,由于redis里面的数据是空的,线程B就需要去mysql当中读取数据,此时数据还是旧值
  3. 线程B从mysql中读取到旧值,由于redis中没有缓存,线程B会进行回写操作,把旧值写回redis(刚刚被A线程删除的旧数据又被写回进redis)
  4. A线程终于将数据更新成功
  5. 后续的所有读操作都是读的脏数据

Redis缓存双写一致性
总结:如果数据库更新失败或超时或返回不及时,导致B线程请求访问缓存时发现redis里面没数据,缓存缺失,B再去读取mysq|时,从数据库中读取到旧值,还写回redis, 导致A白干了

如何解决上诉异常

采用延时双删策略

  1. 线程A先成功删除redis缓存
  2. 线程A更新数据库(更新可能还没有完成)
  3. 线程A更新成功后,先sleep几秒(这几秒表示其他业务逻辑导致耗时延时)
  4. 线程A再次删除redis缓存
  5. 线程B的读取+回写一定是在线程A第二次删除redis缓存之前

加上sleep的这段时间,就是为了让线程B能够先从数据库读取数据,再把缺失的数据写入缓存,然后,线程A再进行删除。所以,线程A sleep的时间,就需要大于线程B读取数据再写入缓存的时间这样一来,其它线程读取数据时,会发现缓存缺失,所以会从数据库中读取最新值。因为这个方案会在第一次删除缓存值后,延迟一段时间再次进行删除,所以我们也把它叫做"延迟双删"
这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

线程A删除完成之后,休眠的时间该如何确定呢?

方案1:

在业务程序运行的时候,统计下线程读数据和写缓存的操作时间,自行评估自己的项目的读数据业务逻辑的耗时,以此为基础来进行估算。然后写数据的休眠时间则在读数据业务逻辑的耗时基础上加百毫秒即可。

方案2:

新启动一个后台监控程序,比如WatchDog监控程序

这种同步淘汰策略,吞吐量降低了怎么办?

将第二次删除作为异步操作,让一个子线程进行异步删除,这样,写的请求就不用沉睡一段时间后了,再返回。这么做,加大吞吐量。

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

异常问题

  1. 线程A更新数据库中的值
  2. 线程A还没有来得及删除缓存的值,此时线程B读取缓存,读取的是缓存旧值
  3. 线程A删除缓存
  4. 其他线程进行redis读取操作,利用回写策略,把缓存更新为最新

虽然会出现缓存删除失败或者来不及,导致请求再次访问redis时缓存命中,读取到的是缓存旧值的这种情况,但是这个方案是最稳妥的

为了解决上诉问题,可以使用消息中间件,来保证数据的最终一致性

Redis缓存双写一致性

流程:

(1)更新数据库数据
(2) 数据库会将操作信息写入binlog日志当中
(3) 订阅程序提取出所需要的数据以及key
(4) 另起一段非业务代码,获得该信息
(5)尝试删除缓存操作,发现删除失败
(6)将这些信息发送至消息队列
(7)重新从消息队列中获得该数据,重试操作

1、可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用Kafka/RabbitMQ等)。
2、当程序没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。
3、如果能够成功地删除或更新,我们就要把这些值从消息队列中去除,以免重复操作,此时,我们也可以保证数据库和缓存的数据一致了,否则还需要再次进行重试
4、如果重试超过的一定次数后还是没有成功,我们就需要向业务层发送报错信息了,通知运维人员。

对于Redis和MySQL(或者其它数据库),不能保证数据实时一致性,也就说无论哪一方进行了修改,另一方都能立刻同步,因为其中还存在许多不确定因素,例如网络延时,因此我们需要保证的是最终一致性文章来源地址https://www.toymoban.com/news/detail-415869.html

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

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

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

相关文章

  • Redis缓存双写一致性之更新策略

    你只要用缓存,就可能会涉及到redis缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 双写一致性,你先动缓存redis还是数据库mysql哪一个?why? 延时双删你做过吗?会有哪些问题? 有这么一种情况,微服务查询redis无m

    2024年02月05日
    浏览(41)
  • Redis缓存问题:穿透,击穿,雪崩,双写一致性等

    在高并发场景下,数据库往往是最薄弱的环节,我们通常选择使用 redis 来进行缓存,以起到缓冲作用,来降低数据库的压力,但是一旦缓存出现问题,也会导致数据库瞬间压力过大甚至崩溃,从而导致整个系统崩溃.今天就聊聊常见的 redis 缓存问题. 缓存击穿 缓存击穿一般指redis中的一

    2024年04月27日
    浏览(36)
  • redis高级篇 缓存双写一致性之更新策略

    缓存通用查询3部曲 redis 中数据,返回redis 中的数据 redis 中没有,查询数据库并返回 完成第二部的同时,将数据库查询结果写到redis,redis和数据库数据一致. 谈谈双写一致性的理解 1.如果redis 中有数据:需要和数据库中的相同 2.如果redis 中无数据: 数据库中的值如果是最新的

    2024年02月06日
    浏览(42)
  • 【redis】缓存双写一致性之工程落地实现(下)

    提示:以下是本篇文章正文内容,下面案例可供参考 如何监听MySQL的变动? MySQL有一个binlog日志 伪装成从机,从主机获取二进制文件 配置不在详述 配置不再详述 a、业务类: 当MySQL进行增删改操作时,后台的canal会立刻监听捕捉到MySQL的二进制binlog日志文件改动,并通过Jav

    2023年04月19日
    浏览(22)
  • Redis双写一致性?

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

    2024年02月16日
    浏览(34)
  • 如何保证数据库和缓存双写一致性?

    如何保证数据库和缓存双写一致性,是面试中经常被问的一个技术问题,程序汪推荐大家有必要好好研究一波 数据库和缓存(比如:redis)双写数据一致性问题,是一个跟开发语言无关的公共问题。尤其在高并发的场景下,这个问题变得更加严重。 我很负责的告诉大家,该问

    2024年01月18日
    浏览(43)
  • Redis(十四)双写一致性工程案例

    https://github.com/alibaba/canal 数据库镜像 数据库实时备份 索引构建和实时维护(拆分异构索引、倒排索引等) 业务 cache 刷新 带业务逻辑的增量数据处理 传统mysql主从复制原理 MySQL的主从复制将经过如下步骤: 当 master 主服务器上的数据发生改变时,则将其改变写入二进制事件日志

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

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

    2024年02月09日
    浏览(32)
  • 如何保证缓存与数据库双写时的数据一致性?

    背景:使用到缓存,无论是本地内存做缓存还是使用 Redis 做缓存,那么就会存在数据同步的问题,因为配置信息缓存在内存中,而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。 共有四种方案: 先更新数据库,后更新缓

    2024年01月24日
    浏览(38)
  • 缓存与数据库双写一致性几种策略分析

    作者:京东零售 于泷 在高并发场景中,为防止大量请求直接访问数据库,缓解数据库压力,常用的方式一般会增加缓存层起到缓冲作用,减少数据库压力。引入缓存,就会涉及到缓存与数据库中数据如何保持一致性问题,本文将对几种缓存与数据库保证数据一致性的使用方

    2023年04月19日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包