Redis学习——数据差别等怎么办?更新缓存失败了又怎么办? ...

打印 上一主题 下一主题

主题 974|帖子 974|积分 2924

引言



  • 最近面试快手的时候被问到了缓存差别等怎么解决?一开始还是很懵的,因为会默认将本身带到一个错误的条件下,就是数据已经差别等了,你怎么办?可能会想,遍历缓存,删除比对数据是不是同等的。停下来想一下,一般是修改数据库的时候,你应该怎么操作缓存,才气保证缓存的同等性。我就知道要么删除缓存后续重建,要么直接修改缓存,但是我对于这两种场景的方法相识的并不多,今天借这个机会,完全整理一下!
正文

数据同中分几种情况?


  • 缓存中有数据,必须要和数据库中的数据同等
  • 缓存中本身没有数据,数据库中的值必须要是最新的
常见的缓存的策略主要有两种,分别是读写缓存和只读缓存,差别策略保证缓存同等性的方式是不一样。详细如下
读写缓存的数据同等性



  • 读写缓存是对于数据的所有增删改都必要在缓存中举行,然后在采取对应的写回策略。主要有两种写回策略

    • 同步直写策略
    • 异步写回策略


同步直写策略


  • 写缓存的时候,同步写数据库,缓存和数据库中的数据是同等的

    • 必要通过变乱机制,保证缓存和数据库更新的原子性,一般是通过tranactional修饰

      • 要么同步更新乐成
      • 要么同步更新失败,下次重试



异步写回策略


  • 写缓存的时候,差别步写入缓存,比及数据从缓存中镌汰的时候,在写入数据库。

    • 问题

      • 一旦缓存瓦解,在缓存中保存的数据,都会瓦解丢失



只读缓存的数据同等性



  • 如果有数据更新(数据增加和修改),直接写入数据库,缓存只负责读数据

    • 在下述过程中,可以看到整个过程是涉及到多步骤多线程的,除了对于数据的操作是具有原子性的,不可打断的,其他的读数据包括数据库同步删除缓存中的数据,都会存在可能的中断,或者其他线程切入的操作


新增数据情况==》不会出现数据差别等的情况



  • 但是删除数据或者修改数据不一样了,因为中间涉及到必要删除缓存中的数据,这一步执行失败会导致数据差别等的情况,详细情况见下一节!
删除和修改数据差别等问题

操作执行失败导致数据差别等

操作分析


  • 对于删除或者修改数据的操作,必要同时修改缓存和操作数据库,任何一方都有可能执行失败,因为没有办法保证双方的操作具有原子性,也就是同时失败或者同时乐成。
  • 下面按照情况,举行逐个分析,分别是删除缓存失败和删除数据库失败两种情况。
删除缓存失败


  • 在下述过程中,删除缓存失败,导致缓存中保存旧版的数据,数据库是新版的数据,两者差别等。

修改数据库失败


  • 修改数据库失败了,删除缓存乐成了,但是在二次访问会重建缓存,将数据库中的脏数据,还原到缓存中,还是会出现访问错误数据的情况

总结


  • 两种操作执行失败带来的数据差别等的情况如下
差别情况潜在问题先删除缓存,在更新数据库数据库更新失败,导致请求再次访问缓存时,发现缓存缺失,重建缓存,读到的还是旧的数据先更新数据库,再删除缓存的缓存删除失败,有请求再次访问缓存时,发现缓存掷中,返回脏数据,和数据库差别等 解决办法



  • 在上述两种情况中,如果修改数据库的操作执行失败了,实在不会产生数据差别等的问题,因为缓存中的数据和数据库中的数据是同等的,后续数据库执行相应的处理策略。但是缓存删除执行失败,就不一样了。以是这个解决办法,主要是针对缓存删除失败的情况而指定的。
消息队列重试


  • 在举行删除或者修改数据时,将数据保存到消息队列中,如果执行失败,再通过消息队列重试执行,如果执行乐成了,就从消息队列中删除对应的值。

在重试这段时间,一般是存在数据差别等性,一般是通过如下方式解决


  • 引入分布式锁,加锁,防止其他数据在访问,会降低并发性
多线程访问导致数据差别等问题



  • 因为同步缓存必要两步,分别是修改数据库和缓存,这两个步骤之间一般来说不会加锁,如许会降低并发性,不加锁就意味着会出现多线程访问问题,导致数据的差别等。
  • 按照更新数据库和缓存的先后,主要分为两种情况,这里详细讨论一下
1、先修改数据库,然后在删除缓存访问
时间线程1线程2问题t1删除数据库中的数据at2读取缓存中的数据a,缓存掷中,读取到不存在的旧值a线程1尚且没有完全删除缓存值,线程2读到缓存中的脏数据at3删除缓存中的数据a



  • 总结

    • 这种情况持续的时间会很短,因为仅仅只要线程1被切换返来,乐成删除缓存中值,就能保证后续数据的同等性,并不必要额外的人工干预。影响小

1、先修改数据库,然后在删除缓存访问
时间线程1线程2问题t1删除缓存中的数据at2读取缓存中的数据a,缓存没有掷中,访问旧版数据库,重建缓存a1、线程1没有更新数据库的值,线程2会读到旧值;只要缓存不逾期中间,后续所有线程读到的都是旧值t3更新数据库中的数据a缓存中是旧值,数据库中是新值,两者不一样! 解决办法===延长双删


  • 修改完数据库之后,再举行一次缓存删除操作,执行两次,保证的缓存的数据重建来自更新之后的数据库
  • 详细指令如下
  1. redis.delKey(x);
  2. db.update(x);
  3. Thread.sleep(N);
  4. redis.delKey(x);
复制代码

总结



  • 保举先删除数据库,再删除缓存,主要缘故原由有以下两点

    • 先删除缓存再删除数据库,导致请求因为缓存缺失而访问数据库,给数据库带来压力
    • 延长双删的时间欠好确定

  • 如果对于数据同等性有强要求

    • 更新数据库的时候,停息redis缓存发送请求,等都弄完了再发送



总结



  • 不总结不知道,之前知道的太浮浅了,关于redis相识的不够深刻,实际上数据差别等不仅仅是删除或者更新缓存那么简朴,中间还会涉及到多线程的问题,因为多个更新数据库和删除缓存并不具有原子性,中间有可能被打断,以是必要分情况举行讨论。
  • 出现数据差别等的情况的以及对应的解决方式有两种,详细如下
数据差别等缘故原由解决办法删除redis执行失败消息队列重试多线程导致数据差别等延长双删策略 参考信息

缓存非常——如何解决缓存和数据库差别等的问题

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

拉不拉稀肚拉稀

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表