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

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

一 面试题引入

  • 你只要用缓存,就可能会涉及到redis缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?
  • 双写一致性,你先动缓存redis还是数据库mysql哪一个?why?
  • 延时双删你做过吗?会有哪些问题?
  • 有这么一种情况,微服务查询redis无mysql有,为保证数据双写一致性回写redis你需要注意什么?双检加锁策略你了解过吗?如何尽量避免缓存击穿?
  • redis和mysql双写100%会出纰漏,做不到强一致性,你如何保证最终一致性?

二 缓存双写一致性

  • 如果redis中有数据:需要和数据库中的值相同
  • 如果redis中无数据:数据库中的值要是最新值,且准备回写redis
  • 缓存按照操作来分,细分2种
    • 只读缓存:
    • 读写缓存:

      同步直写策略:

      • 写数据库后也同步写redis缓存,缓存和数据库中的数据一致。
      • 对于读写缓存来说,要想保证缓存和数据库中的数据一致,就要采用同步只写策略。

      异步缓写策略:

      • 正常业务允许中,mysql数据变动了,但是可以在业务上容许出现一定时间后才作用于redis,比如仓库、物流系统。
      • 异常情况出现了,不得不将失败的动作重新修补,有可能需要借助Kafka或者RabbitMQ等消息中间件,实现重试重写。

三 双写双检加锁策略

Redis缓存双写一致性之更新策略
当高并发的情况下,采用双检加锁策略:
多个线程同时去查询数据库的这条记录,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

public String get(String key){
	String value = redis.get(key);//查询缓存
	if(value != null){
		//缓存存在直接返回
		return value;
	}else{
		//缓存不存在则对方法加锁
		//加锁请求量很大,缓存过期(对于高QPS的优化)
		synchronized(TestFuture.class){
			value = redis.get(key);//再查一遍redis
			if(value != null){
				//查到数据直接返回
				return value;
			}else{
				//二次查询缓存也不存在,直接查DB
				value = dao.get(key);
				//数据缓存
				redis.setnx(key,value,time);
				//返回
				return value;
			}
		}
	}
}

四 数据库和缓存一致性的集中更新策略

4.1 最终一致性

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

4.2 可以关机的情况下

挂牌报错、凌晨升级,温馨提示、服务降级
使用单线程,这样重量级的数据操作最好不要多线程。

4.3 不能关机的情况下,四种更新策略

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

  • 更新redis失败,导致数据库和缓存redis里面数据不一致,读到redis脏数据。
  • 先更新数据库,再更新缓存,A/B两个线程发起调用。

    异常情况下:多线程环境下,A/B两个线程有快有慢,导致写入mysql顺序与更新redis顺序不一致,使两端数据不一致。

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

不推荐,业务上一般把mysql作为底单数据库,保证最后解释。

异常情况下:多线程环境下,A/B两个线程有快有慢,导致写入redis顺序与更新mysql顺序不一致,使两端数据不一致。

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

  • 异常情况

    • A线程先成功删除了redis里面的数据,然后去更新mysql,此时mysql正在更新中,还没有结束(比如网络延迟),B线程突然出现要读取缓存数据。
    • 此时redis里面的数据时空的,B线程来读取,此时有2个问题:
      • B从mysql中获取到了旧值:B线程发现redis里没有(缓存缺失)马上去mysql里面读取,从数据库里面读取来的是旧值
      • B会把获取到的旧值写回redis:获得旧值数据后返回前台并回写进redis(刚被A线程删除的旧数据有极大可能又被写回了)
    • A线程更新完mysql,发现redis里面的缓存是脏数据,
  • 解决方案:采用延时双删策略Redis缓存双写一致性之更新策略
    加上sleep的这段时间,就是为了让线程B能够先从数据库读取数据,再把缺失的数据写入缓存。然后,线程A再进行删除。所以,线程A sleep的时间,就需要大于线程B读取数据再写入缓存的时间。这样一来,其它线程读取数据时,会发现缓存缺失,所以会从数据库中读取最新值。因为这个方案会在第一次删除缓存值后,延迟一段时间再次进行删除,所以我们也把它叫做“延迟双删”。

  • 延时双删策略问题引入:

    • 这个删除该休眠多久呢?

      线程A sleep的时间,就需要大于线程B读取数据再写入缓存的时间。
      这个时间如何确定呢?
      第一种方法:在业务程序运行的时候,统计下线程读数据和写缓存的操作时间,自行评估自己项目的读数据业务逻辑的耗时,以此为基础来进行估算,然后写数据的休眠时间则在数据业务逻辑的耗时基础上加百毫秒即可。
      这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。
      第二种方法:新启动一个后台监控程序(如:WatchDog)

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

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

4.3.4 先更新数据库,再删除缓存(主流)–实现最终一致性

  • 异常问题:假如缓存删除失败或者来不及,导致请求再次访问redis时缓存命中,读取到的是缓存旧值。
  • 解决方案:Redis缓存双写一致性之更新策略
  1. 可以把要删除的缓存值或者是要更新的数据库值暂存到消息队列中(例如使用Kafla/RabbitMQ等)。
  2. 当程序没有能够成功地删除缓存值或者是更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或者更新。
  3. 如果能够成功地删除或更新,我们就要把这些值从消息队列中去除,以免重复操作,此时,我们也可以保证数据库和缓存的一致性,否则还需要再次进行重试。
  4. 如果重试超过了一定次数后还没有成功,我们就需要向业务层发送报错信息了,通知运维人员。

五 总结

5.1 如何选择方案?利弊如何?

优先使用先更新数据库,再删除缓存的方案(先更库–>后删库),理由如下:

  1. 先删除缓存值再更新数据库,有可能导致请求因缓存缺失而访问数据库,给数据库带来压力导致打满mysql。
  2. 如果业务应用中读取数据库和写缓存的时间不好估算,那么延迟双删中的等待时间就不好设置。

Redis缓存双写一致性之更新策略文章来源地址https://www.toymoban.com/news/detail-454407.html

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

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

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

相关文章

  • Redis缓存(双写一致性问题)

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

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

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

    2023年04月17日
    浏览(46)
  • redis的缓存更新策略以及如何保证redis与数据库的数据一致性

    redis的缓存更新策略有这么几种: 1、由应用直接和redis以及数据库相连接:         查询数据时,应用去redis中查询,查不到的话再由应用去数据库中查询,并将查询结果放在redis;         更新数据时,由应用去触发redis数据的删除以及数据库的update。 2、应用只跟redi

    2024年02月13日
    浏览(57)
  • Redis高级系列-缓存双写一致性

    Redis缓存双写一致性是指在更新数据库数据后,同时更新缓存数据以保持数据一致性的策略,总的来说,就是 写入redis 和 写入数据库 的数据要保持一致 2.1 Cache Aside Pattern(旁路缓存模式) 旁路缓存模式,字面意思理解:缓存是旁路,缓存相对与应用程序和数据库是旁路,应用

    2024年01月20日
    浏览(60)
  • 【Redis】聊一下缓存双写一致性

    缓存虽然可以提高查询数据的的性能,但是在缓存和数据 进行更新的时候 其实会出现数据不一致现象,而这个不一致其实可能会给业务来带一定影响。无论是Redis 分布式缓存还是其他的缓存机制都面临这样的问题。 数据一致性 缓存中有数据,那么缓存的数据和数据库的数据

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

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

    2023年04月19日
    浏览(50)
  • Redis缓存问题:穿透,击穿,雪崩,双写一致性等

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

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

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

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

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

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

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

    2024年01月18日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包