安排 Spring 缓存驱逐?

问题描述 投票:0回答:8

是否可以将 Spring 缓存驱逐安排在每天的午夜?

我已阅读Springs Cache Docs,但没有发现任何有关计划缓存驱逐的信息。

我需要每天清除缓存并重新缓存它,以防应用程序之外发生一些更改。

java spring spring-cache
8个回答
47
投票

尝试使用@Scheduled 示例:

@Scheduled(fixedRate = ONE_DAY)
@CacheEvict(value = { CACHE_NAME })
public void clearCache() {  
    log.debug("Cache '{}' cleared.", CACHE);    
}

您还可以将 cron 表达式与@Scheduled 一起使用。


17
投票

如果您在带参数的方法上使用@Cacheable,则永远不要忘记@CacheEvict上的allEntries=true注释属性,否则您的调用只会逐出您提供给clearCache()方法的关键参数,这没什么= > 您不会从缓存中清除任何内容。


6
投票

也许不是最优雅的解决方案,但是

@CacheEvict
不起作用,所以我直接选择了
CacheManager

此代码通过调度程序清除名为

foo
的缓存:

class MyClass {

    @Autowired CacheManager cacheManager;

    @Cacheable(value = "foo")
    public Int expensiveCalculation(String bar) {
        ...
    }

    @Scheduled(fixedRate = 60 * 1000)
    public void clearCache() {
        cacheManager.getCache("foo").clear();
    }
}

3
投票

请按照以下代码操作,相应地更改 cron 表达式。我设置了3分钟

  1. 创建一个班级。

  2. 在类中使用以下方法。

    class A 
    {
    @Autowired CacheManager cacheManager;
    
    @Scheduled(cron ="0 */3 * ? * *")
        public void cacheEvictionScheduler()
        {
             logger.info("inside scheduler start");
            //clearCache();
             evictAllCaches();
            logger.info("inside scheduler end");
        }
    
    public void evictAllCaches() {
             logger.info("inside clearcache");
            cacheManager.getCacheNames().stream()
              .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
        }
    }
    

2
投票

我知道这个问题已经很老了,但我找到了一个对我有用的更好的解决方案。也许这会对其他人有所帮助。

因此,确实可以进行计划的缓存驱逐。这是我在我的案例中所做的。

@Scheduled 和 @CacheEvict 这两个注释似乎不能一起工作。 因此,您必须将调度方法和缓存逐出方法分开。 但由于整个机制基于代理,因此只有对类的公共方法的外部调用才会触发缓存驱逐。这是因为同一类的方法之间的内部调用不通过 Spring 代理。

我设法以与 Celebes 相同的方式修复它(参见评论),但进行了改进以避免两个组件。

@Component
class MyClass
{

    @Autowired
    MyClass proxiedThis; // store your component inside its Spring proxy.

    // A cron expression to define every day at midnight
    @Scheduled(cron ="0 0 * * *")
    public void cacheEvictionScheduler()
    {
        proxiedThis.clearCache();
    }

    @CacheEvict(value = { CACHE_NAME })
    public void clearCache()
    {
        // intentionally left blank. Or add some trace info.
    }    
}

2
投票

将注释 @Scheduled 与 cron 表达式一起使用,将 @CacheEvict 与 allEntries = true 一起使用,如下所示:

/*
* This clears the entire cache called "myCache" everyday, 
* at 00.00 (am) in the time zone of the server.
*/
@Scheduled(cron = "0 0 0 * * ?")
@CacheEvict(value = "myCache", allEntries = true)
public void clearMyCache() {}

如果您想在清除缓存之前添加逻辑,您可以在方法主体中执行此操作:

/*
* This clears the entire cache called "myCache" everyday, 
* at 00.00 (am) in the time zone of the server.
*/
@Scheduled(cron = "0 0 0 * * ?")
@CacheEvict(value = "myCache", allEntries = true)
public void clearMyCache() {

    // Add logic here
    log.debug("Clearing myCache now");

}

CacheEvict 会在代码运行后发生,并且仅当它不抛出任何异常时才会发生。您可以通过添加“beforeInspiration = true”来更改它,在这种情况下,它会首先逐出缓存,然后运行您的代码。


1
投票

Spring 缓存框架是事件驱动的,即

@Cacheable
@CacheEvict
仅在调用相应方法时才会触发。

但是,您可以利用底层缓存提供程序(记住 Spring 缓存框架只是一个抽象,本身并不提供缓存解决方案)来自行使缓存失效。例如EhCache有一个属性即。

timeToLiveSeconds
指示缓存处于活动状态之前的时间。但这不会为您重新填充缓存,除非调用
@Cacheable
带注释的方法。

因此,对于特定时间(如上所述的午夜)的缓存驱逐和重新填充,请考虑在 Spring 中实现后台计划服务,这将根据需要触发缓存驱逐和重新填充。未提供开箱即用的预期行为。

希望这有帮助。


0
投票

您可以定义计划的缓存驱逐,它可以在 cron 表达式上运行。

例如下面的代码将清除缓存

@CacheEvict(value = "movieList", allEntries = true)
  @Scheduled(cron = "@midnight", zone = "UTC")
  public void evictMoviesCache() {
    // Nothing to do. Cache eviction schedule, you can optionally log here.
  }

另一种变化是

   @CacheEvict(value = "movieList", allEntries = true)
   @Scheduled(fixedDelay = 12, timeUnit = TimeUnit.HOURS)
      public void evictMoviesCache() {
        // Nothing to do. Cache eviction schedule, you can optionally log here.
      }
© www.soinside.com 2019 - 2024. All rights reserved.