zoukankan      html  css  js  c++  java
  • Redis更新缓存同步数据库的理解

    问题:当数据库有数据更新时,怎样保证redis缓存中的数据与数据库数据一致?

    Redis更新的正确方法

      看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

    视图分析:

    写流程(更新策略)

      1.先淘汰 cache(删除缓存);
      2.再写 DB(更新数据库)。
    读流程

      1.先读 cache,如果数据命中 hit 则返回;
      2.如果数据未命中 miss 则读 DB;
      3.将 DB 中读取出来的数据入缓存。


    什么情况下可能出现缓存和数据库不一致呢?

    在分布式环境下,数据的读写都是并发的,上游有多个应用,通过一个服务的多个部署(为了保证可用性,一定是部署多份的),对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序,也就是说后发出的读请求很可能先完成(读出脏数据):

    1.发生了写请求 A,A 的第一步淘汰了 cache(如上图中的1);
    2.A 的第二步写数据库,发出修改请求(如上图中的2);
    3.发生了读请求 B,B 的第一步读取 cache,发现 cache 中是空的(如上图中的步骤3);
    4.B 的第二步读取数据库,发出读取请求,此时 A 的第二步写数据还没开始,读出了一个脏数据放入 cache(如上图中的步骤4)。


    最终导致缓存与数据库不一致。

    总结

    先更新数据库,后删除缓存(建议,使用场景最多),但是,是不是这个就不会有并发问题了?不是的,比如,一个是读操作,但是没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,所以,会造成脏数据。

  • 相关阅读:
    [转载]小谈网络游戏同步
    [ASE][Daily Scrum]11.06
    [Proposal]Tank Battle——Infinite
    [proposal][app]Watch your time!
    [Proposal]Nano-Diary(纳日记)
    LaTeX中用BibTex管理参考文献
    matlab化简符号表达式
    placeholder颜色变化
    链接图片外边出现蓝框(IE8/IE9/IE10)
    图标排列
  • 原文地址:https://www.cnblogs.com/rong0912/p/12157666.html
Copyright © 2011-2022 走看看