Redis更新的正确方法

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

视图分析:shell

写流程(更新策略)数据库

  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)。

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

先更新数据库,后删除缓存建议,使用场景最多),可是,是否是这个就不会有并发问题了?不是的,好比,一个是读操做,可是没有命中缓存,而后就到数据库中取数据,此时来了一个写操做,写完数据库后,让缓存失效,而后,以前的那个读操做再把老的数据放进去,因此,会形成脏数据。3d

相关文章
相关标签/搜索