前言

在构建高性能应用程序和系统时,选择适当的缓存策略是至关重要的。数据库和缓存之间的关系直接影响系统的性能、可伸缩性和稳定性。下面讨论几种常见的缓存策略,探讨它们的特点以及在实际应用中的优劣之处。

旁路缓存(Cache-Aside)策略

以数据库中的数据为准,缓存中的数据都是按需加载的。

读取过程:

    1. 从缓存中读取数据;
    2. 若缓存命中,则直接返回数据;
    3. 若缓存未命中,则从数据库中查询数据并写入缓存,返回给用户。

写入过程:

    1. 更新数据库中的记录;
    2. 使缓存中的记录失效或更新缓存记录。

  1.  

值得注意的是旁路缓存在更新时,我们若选择先删除缓存记录再更新数据库中的记录的话,那么在我们删除缓存后,可能存在一个并发的新请求获取缓存数据未命中而读取数据库中失效数据后再更新到缓存导致缓存中的数据仍旧是失效数据的情况。

直读(Read-Through)

在读取穿透的策略中,缓存位于应用程序和数据库之间。

过程:

  1. 应用程序从缓存读取数据;
  2. 若缓存命中,立即返回数据;
  3. 若缓存未命中,缓存组件从数据库中获取缺失的数据,将其返回给用户。

直读策略也适用于读取密集型工作负载。读取穿透和缓存旁路策略之间的主要区别在于,在缓存旁路策略中,应用程序负责获取数据并填充缓存,而在读取穿透设置中,这一逻辑由库或某个独立的缓存提供程序完成。读取穿透设置与缓存旁路类似,可能存在缓存与数据库之间的数据不一致性的问题。

直写(Write-Through)

区别于前两种策略,直写会先向缓存写入数据然后由缓存组件立即写入数据库。

写入穿透策略的优点是可以确保缓存中存在所有写入的数据,并且新的读取不会因为从主数据库请求数据而延迟。如果仅仅采用这种设计,则存在一个重要的缺点,即额外的写入延迟,因为操作必须经过缓存然后才能到达数据库。虽然这个过程应该是即时的,但实际上是连续进行了两次写入。

可以选择将写入穿透与读取穿透缓存结合使用。这种策略将采用前面提到的读取穿透缓存策略的所有好处,而且消除了数据不一致性的潜在风险。

回写(Write-Back)

回写策略与直写策略几乎完全相同,区别只是缓存不会立即写入数据库,而是延迟一段时间后进行写入。

数据延迟写入数据库可以减轻写入密集型负载的压力。

回写策略与直读策略的组合适用于混合型工作负载。缓存和数据库之间的写入延迟可以提高整体写入性能,若支持批处理,还可以减少总体写入次数。但在缓存发生故障的情况下,这种延迟可能会导致数据丢失,若批处理或延迟写入没有被执行,这种延迟会存在丢失数据的风险。

绕写(Write-Around)

过程:

  • 在写入数据时,应用程序直接将数据写入数据源,而不涉及缓存。

绕写策略可以与旁路缓存或直读策略结合使用。在这种组合下,数据始终被写入数据库,并从缓存中读取。

引用

《牧羊人》

费尔南多·佩索阿
思考令人不适,就像走在雨里。 当风增强时,似乎雨下得更大。