概述

跟着时代的开展,服务体系架构也已经由最初的单体架构转变为分布式、微服务架构形式。 从数据体量上来看,各体系存储的数据量越来越大,数据的查询功能越来越低。 此刻,就需求咱们不断的进行优化,最常用的便是引进缓存。 而引进缓存后,咱们如何保证缓存和数据库的一致性呢?

常见战略形式

常见更新战略有Cache Aside (旁路缓存)、Read/Write Through (读穿 / 写穿)、Write Behind/Back(写回)三种形式, 其中旁路缓存是目前使用最广泛的一种方式。

Cache Aside (旁路缓存)

  • 失效:使用程序先从cache取数据,没有获取到,则从数据库中取数据,成功后,放到缓存中。
  • 射中:使用程序从cache中取数据,取到后回来。
  • 更新:先把数据存到数据库中,成功后,再让当时缓存失效

掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!

是不是Cache Aside这个就不会有并发问题了?

不是的,比如,一个是读操作,可是没有射中缓存,然后就到数据库中取数据,此刻来了一个写操作,写完数据库后,让缓存失效, 然后,之前的那个读操作再把老的数据放进去,所以,会造成脏数据。

为什么这种思路存在这么显着的问题,却还具有那么广泛的使用呢?由于这个case实践上呈现的概率十分低,产生这个case需求具有如下4个条件

  1. 读操作读缓存失效
  2. 有个并发的写操作
  3. 写操作比读操作更快
  4. 读操作早于写操作进入数据库,晚于写操作更新缓存

而实践上数据库的写操作会比读操作慢得多,而且还要锁表,而读操作必需在写操作前进入数据库操作,而又要晚于写操作更新缓存。 一切的这些条件都具有的概率根本并不大。并且即使呈现这个问题还有一个缓存过期时刻来主动兜底。

为什么删去而不是更新缓存?

现在思考一个问题,为什么是删去缓存,而不是更新缓存呢? 删去一个数据,相比更新一个数据更加轻量级,出问题的概率更小。

在实践事务中,缓存的数据可能不是直接来自数据库表,或许来自多张底层数据表的聚合。 比如产品详情信息,在底层可能会相关产品表、价格表、库存表等,假如更新了一个价格字段, 那么就要更新整个数据库,还要相关的去查询和汇总各个周边事务体系的数据,这个操作会十分耗时。

从另外一个角度,不是一切的缓存数据都是频频拜访的,更新后的缓存可能会长时刻不被拜访, 所以说,从核算资源和全体功能的考虑,更新的时分删去缓存,等到下次查询射中再填充缓存,是一个更好的方案。

体系规划中有一个思想叫 Lazy Loading,适用于那些加载代价大的操作,删去缓存而不是更新缓存,便是懒加载思想的一个使用。

Read/Write Through (读穿 / 写穿)

在这种情况下,使用程序将缓存视为主数据存储。使用程序不再和数据库交互,而是由缓存和数据库交互,相当于更新数据库的操作由缓存自己代理了。

掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!

  • 失效:使用程序先从cache取数据,没有获取到,则cache从数据库中取数据,成功后,放到缓存中。
  • 射中:使用程序从cache中取数据,取到后回来。
  • 更新:先把数据更新到缓存中,还将数据更新到数据库。

掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!

Write Behind/Back(写回)

在这种缓存战略中,先更新缓存,然后在设定的一段时刻后异步更新数据库。 此战略特别适合写多的场景,由于发生写操作的时分, 只需求更新缓存,就立马回来了。 Write-behind缓存提高了体系功能,由于用户(通常)不必等候对数据库的更改,可是异步机制会增加数据延迟不一致的危险。

掌握分布式环境缓存更新策略,提高缓存与数据库双写一致性!

结语

总结

三种缓存形式优缺点:

Cache Aside 更新形式完成起来比较简单,可是需求保护两个数据存储,一个是缓存(Cache),一个是数据库(Repository)。

Read/Write Through 更新形式只需求保护一个数据存储(缓存),可是完成起来要复杂一些。

Write Behind Caching 更新形式和Read/Write Through 更新形式相似,区别是Write Behind Caching 更新形式的数据持久化操作是异步的, 可是Read/Write Through 更新形式的数据持久化操作是同步的。

参考文章

coolshell.cn/articles/17… www.cnblogs.com/xiaolincodi…