spring应用启动时如何制作缓存依赖于其他缓存

Posted

技术标签:

【中文标题】spring应用启动时如何制作缓存依赖于其他缓存【英文标题】:How to make cache depends on other caches on startup of spring application 【发布时间】:2019-12-30 02:51:17 【问题描述】:

在我们的多模块项目中,我们在不同的模块中存在不同的缓存。我们在@PostConstruct 中的服务器启动时填充所有这些缓存。 现在一些缓存依赖于其他可能存在于不同模块中的缓存。因此,它要求在依赖于该缓存的缓存之前填充一些缓存。 1. 我们如何在 Spring 中做到这一点?我可以利用任何设计模式吗? 2. 如果缓存更新了,我们如何将更新后的更改实时传播到那些依赖更新缓存的缓存?

module 1---
    Cachce1

module 2--
    Cache2

module 3--
    Cache3

class Cache1 
  private ConcurrentMap<> cache; 
  @PostConstruct() 
    cache = filleCache();
  

class Cache2 
  @Autowired
  private Cache1 cache1;
  private ConcurrentMap<> cache; 
  @PostConstruct() 
    cache = cache1;
  

class Cache3 
  @Autowired
  private Cache2 cache2;
  private ConcurrentMap<> cache; 
  @PostConstruct() 
    cache = cache2;
  

【问题讨论】:

【参考方案1】:

Dependencies:初始化顺序通常由 DI 框架正确完成。所以Cache2 post 构造在Cache1 完全初始化之后运行。如果您仅在 CuncurrentMap 中缓存完整的数据集,则可以使用 memoization,请参阅 https://dzone.com/articles/need-micro-caching-memoization

避免缓存堆叠。有时避免在中间层中缓存更简单。一种简单的方法是缓存数据的来源,例如持久层,然后缓存数据输出的位置,例如响应 sn-ps 或完整响应。由于无论如何都将完整的数据缓存在最顶层的缓存中,因此中间缓存也可能不会得到任何命中。

这在很大程度上取决于数据的类型以及它在下一层使用的频率。

我们如何传播这个更新的变化?

您有多种选择。如果 module1 知道它的依赖关系,您可以调用 module2 和 3 的重新加载。如果 module1 代码不应该依赖于它的客户端,则使用事件侦听器模式。根据您的数据来自哪里,已经有现有的机制。查找 Spring Data 事件、数据库的更改数据捕获功能、数据库或持久层的触发器。

您可以通过使用缓存条目的过期时间来保持简单,并在一段时间后简单地更新/重新加载您的数据。但是,过期和缓存堆叠本身就是一个问题。如果您使用 5 分钟的固定到期时间,则有效到期时间会累加每一层。所以对于三层,数据可能会在 5 或 15 分钟后刷新。为了避免这种情况,我们通过缓存层传播了一个到期时间点以及数据。

【讨论】:

以上是关于spring应用启动时如何制作缓存依赖于其他缓存的主要内容,如果未能解决你的问题,请参考以下文章

如何在启动更新版本的应用程序时清除浏览器缓存?

spring的循环依赖及使用三级缓存解决循环依赖;注入bean到spring容器中

0源码基础学习Spring源码系列——Spring如何解决循环依赖

使用@Cacheable 的Spring 缓存在启动@PostConstruct 时不起作用

Spring三级缓存

SpringBoot-缓存管理