为何你的缓存更新策略是先更新数据库后删除缓存,讲讲其余的状况有什么问题?

问题:怎么保持缓存与数据库一致?数据库

要解答这个问题,咱们首先来看不一致的几种状况。我将不一致分为三种状况缓存

  1. 数据库有数据,缓存没有数据;
  2. 数据库有数据,缓存也有数据,数据不相等;
  3. 数据库没有数据,缓存有数据。

在讨论这三种状况以前,先说明一下我使用缓存的策略,也是大多数人使用的策略,叫作 Cache Aside Pattern。酷壳里的 缓存更新的套路 一文,很值得一读,个人策略也是从他那学来的。 简而言之,就是ide

  1. 首先尝试从缓存读取,读到数据则直接返回;若是读不到,就读数据库,并将数据会写到缓存,并返回。
  2. 须要更新数据时,先更新数据库,而后把缓存里对应的数据失效掉(删掉)。

由于:线程

  1. 读的逻辑你们都很容易理解,谈谈更新。若是不采起我提到的这种更新方法,你还能想到什么更新方法呢?大概会是:先删除缓存,而后再更新数据库。这么作引起的问题是,若是A,B两个线程同时要更新数据,而且A,B已经都作完了删除缓存这一步,接下来,A先更新了数据库,C线程读取数据,因为缓存没有,则查数据库,并把A更新的数据,写入了缓存,最后B更新数据库。那么缓存和数据库的值就不一致了。方法

  2. 另外有人会问,若是采用你提到的方法,为何最后是把缓存的数据删掉,而不是把更新的数据写到缓存里。这么作引起的问题是,若是A,B两个线程同时作数据更新,A先更新了数据库,B后更新数据库,则此时数据库里存的是B的数据。而更新缓存的时候,是B先更新了缓存,而A后更新了缓存,则缓存里是A的数据。这样缓存和数据库的数据也不一致。数据

按照我提到的这种更新缓存的策略,理论上也是有不一致的风险的,酷壳的文章有提到,只不过几率很小,咱们暂时能够不考虑,后面咱们有其余手段来补救。 讨论完使用缓存的策略,咱们再来看这三种不一致的状况。时间

  1. 对于第一种,在读数据的时候,会自动把数据库的数据写到缓存,所以不一致自动消除
  2. 对于第二种,数据最终变成了不相等,但他们以前在某一个时间点必定是相等的(无论你使用懒加载仍是预加载的方式,在缓存加载的那一刻,它必定和数据库一致)。这种不一致,必定是因为你更新数据所引起的。前面咱们讲了更新数据的策略,先更新数据库,而后删除缓存。所以,不一致的缘由,必定是数据库更新了,可是删除缓存失败了。
  3. 对于第三种,状况和第二种相似,你把数据库的数据删了,可是删除缓存的时候失败了。

所以,最终的结论是,须要解决的不一致,产生的缘由是更新数据库成功,可是删除缓存失败。 我想出的解决方案大概有如下几种:解决方案

  1. 对删除缓存进行重试,数据的一致性要求越高,我越是重试得快。
  2. 按期全量更新,简单地说,就是我按期把缓存所有清掉,而后再全量加载。
  3. 给全部的缓存一个失效期。

第三种方案能够说是一个大杀器,任何不一致,均可以靠失效期解决,失效期越短,数据一致性越高。可是失效期越短,查数据库就会越频繁。所以失效期应该根据业务来定。懒加载

相关文章
相关标签/搜索