当前位置: 首页 > 知识库问答 >
问题:

使用Spring缓存抽象的异步缓存更新

段曦
2023-03-14

使用Spring的缓存抽象,如何让缓存异步刷新条目,同时仍返回旧条目?

我试图使用Spring的缓存抽象来创建一个缓存系统,在相对较短的“软”超时之后,缓存条目可以刷新。然后,当查询它们时,返回缓存的值,并启动异步更新操作来刷新条目。我也会

Guava的缓存生成器允许我指定缓存中的条目应该在一定时间后刷新。然后可以用异步实现覆盖缓存加载器的reload()方法,允许返回陈旧的缓存值,直到检索到新值。但是,Spring缓存似乎没有使用底层Guava缓存的CacheLoader

可以使用Spring的缓存抽象实现这种异步缓存刷新吗?

编辑以澄清:使用Guava的CacheBuilder,我可以使用刷新后写()来获得我想要的行为。例如从Guava缓存解释:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
   .maximumSize(1000)
   .refreshAfterWrite(1, TimeUnit.MINUTES)
   .build(
       new CacheLoader<Key, Graph>() {
         public Graph load(Key key) { // no checked exception
           return getGraphFromDatabase(key);
         }

         public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
           if (neverNeedsRefresh(key)) {
             return Futures.immediateFuture(prevGraph);
           } else {
             // asynchronous!
             ListenableFutureTask<Graph> task = ListenableFutureTask.create(new Callable<Graph>() {
               public Graph call() {
                 return getGraphFromDatabase(key);
               }
             });
             executor.execute(task);
             return task;
           }
         }
       });

然而,我无法找到使用Spring的@Cacheable抽象来获得refreshAfterWrite()行为的方法。

共有2个答案

史商震
2023-03-14

在一个使用Spring缓存抽象的项目中,我做了以下事情来达到相同的目标,但仍然设法隐藏缓存的实际供应商,即它应该与Spring支持的任何缓存提供程序一起工作(目前是Guava,但如果需要,应用程序可以切换到集群缓存提供程序)。

核心概念是“捕获”缓存使用模式,并在另一个后台线程中“重播”这些操作,可能由调度器执行。

如果我想保持代码的非侵入性,它需要对“捕获”部分使用反射和一些AOP编程,幸运的是,Spring AOP提供了我需要的所有工具集。

鲁华茂
2023-03-14

也许你可以尝试以下方式:

>

  • 配置缓存:

    @Configuration
    @EnableCaching
    public class CacheConfig {
    
        @Bean
        public CacheManager cacheManager() {
            SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
    
            GuavaCache chache= new GuavaCache("cacheKey", CacheBuilder.newBuilder().build());
    
            simpleCacheManager.setCaches(Arrays.asList(cacheKey));
    
            return simpleCacheManager;
        }
    }
    

    假设一个字符串,读取要缓存的值(我使用服务作为示例)

    @Service
    public class MyService{
    
        @Cacheable("cacheKey")
        public String getStringCache() {
            return doSomething();
        }
    
        @CachePut("cacheKey")
        public String refreshStringCache() {
            return doSomething();
        }
        ...
    }
    

    getStringCache()刷新StringCache()都调用相同的函数以检索要缓存的值。控制器仅调用getStringCache()

    使用计划任务文档刷新缓存

    @Configuration
    @EnableScheduling
    public class ScheduledTasks {
    
        @Autowired
        private MyService myService;
    
        @Scheduled(fixedDelay = 30000)
        public void IaaSStatusRefresh(){
            myService.refreshStringCache();
        }
    }
    

    通过这种方式,计划任务强制每30秒刷新一次缓存。任何访问getStringCache()的人都会在缓存中找到更新的数据。

  •  类似资料:
    • 32.2 缓存抽象 缓存(Cache) vs 缓冲区(Buffer) 缓存和缓冲区两个术语往往可以互换着使用。但注意,它们代表着不同的东西。 缓冲区是作用于快和慢速实体之间的中间临时存储。 一块缓冲区必须等待其他并影响性能,通过允许一次性移动整个数据块而不是小块来缓解。数据从缓冲区读写只有一次。因此缓冲区对至少一方是可见的。 另一方面,缓存根据定义是隐性的,双方不会知道缓存的发生。它提高了性能,

    • 我试图使用Spring Boot与咖啡因和一些注释函数。在我们的测试中,对控制器endpoint的异步调用出现了一些问题,这些问题似乎与我们使用非异步缓存的事实有关。 在做一些研究时,我看到了很多使用Caffeine手动使用的例子,但是在和Spring Boot和注释中找不到任何东西。看起来和具有非常不同的API。是否可以异步使用默认的Spring Boot? 谢谢

    • 在谷歌代码上提供的ehcache spring注解库中,一个配置选项“创建缺少的缓存”可用于动态创建缓存(缓存未在ehcache.xml中定义)。纯spring ehcache抽象(spring 3.1.1)中是否有类似的配置?或者有没有其他方法可以使用spring ehcache抽象创建动态缓存?

    • Spring缓存抽象支持多值查询吗? 而不是: 这是支持的吗?它会单独缓存每一本返回的藏书吗? 谢谢!

    • 一、简介 当对PHPSSO进行修改后,执行此操作。 二、功能演示 更新应用列表缓存。如下图所示:

    • 我正在向spring启动项目添加缓存。应用程序。yml包含 @EnableCaching位于主应用程序上,我已将@Cacheable(“cacheName”)添加到该方法中,同一类中的另一个方法不会调用它。 在测试中,我看到缓存是NoOp类型的,而不是咖啡因。我已确保在所有情况下都使用正确的导入(springframework)。我还应该在哪里启用缓存?