在Spring Boot中重新加载/刷新缓存

时间:2019-06-05 10:31:24

标签: java spring-boot caching memcached ehcache

我正在使用Spring Boot,并且为了缓存我正在使用Ehcache。到目前为止,一切正常。但是现在我必须重新加载/刷新,以便如何执行此操作,以使我的应用程序不会出现任何停机时间。

我已经在Spring Ehcache中尝试了许多方法,但是没有用,否则,其他人必须编写调度程序并重新加载数据。

@Override
@Cacheable(value="partTypeCache", key="#partKey")
public List<PartType> loadPartType(String partKey) throws CustomException {
        return productIdentityDao.loadPartType();
}

6 个答案:

答案 0 :(得分:4)

显然,关于您的问题的所有评论都是正确的。您使用CacheEvict。我在这里找到了解决方法:https://www.baeldung.com/spring-boot-evict-cache,看起来像这样:

您所要做的就是创建名为例如CacheService和create方法将逐出您拥有的所有缓存对象。然后,您可以对@Scheduled方法进行注释,并设置间隔率。

@Service
public class CacheService {

    @Autowired
    CacheManager cacheManager;

    public void evictAllCaches() {
        cacheManager.getCacheNames().stream()
          .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
    }

    @Scheduled(fixedRate = 6000)
    public void evictAllcachesAtIntervals() {
        evictAllCaches();
    }

}

答案 1 :(得分:0)

尝试这样的方法,如评论中所述:

    @Caching(evict={@CacheEvict(value="partTypeCache", key="#partKey")})
    public boolean deletePartType(String partKey) { 
      //when this method is invoked the cache is evicted for the requested key
    }

答案 2 :(得分:0)

您知道要更新哪些partKey吗?如果不这样做,则必须从缓存本身中找到密钥。您可以使用@CachePut来更新缓存值,而无需停机。我的建议的效果不会很好,但是应该可以完全满足您的要求。

专门针对EhCache:

public void renewCache() {
    net.sf.ehcache.EhCache cache = (net.sf.ehcache.EhCache) org.springframework.cache.CacheManager.getCache("partTypeCache").getNativeCache();
    for (Object key : cache.getKeys()) {
          updatePartTypeCache((String) key)
    }
}

@CachePut(value="partTypeCache", key="#partKey")
public List<PartType> updatePartTypeCache(String partKey) throws CustomException {
        return productIdentityDao.loadPartType();
}

要清楚,最糟糕的部分是从现有缓存中获取密钥。如果要在缓存中保留一小部分“热”零件,则可以只调用updatePartTypeCache。

答案 3 :(得分:0)

许多人建议使用 @CacheEvict 的选项是正确的。此外,为了确保您的缓存(近)始终加载最新数据,即使数据库中的数据更新超出了您正在运行的应用程序的范围,您也需要定期重新加载整个数据集,其间隔与应用程序的 SLA 相匹配。在建议的解决方案 above 中,添加重新加载所有数据的逻辑,如下所示:

@Service
public class CacheService {

    @Autowired
    CacheManager cacheManager;

    public void refreshAllCaches() {
        cacheManager.getCacheNames().stream()
          .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
        // reload whole dataset here, dummy example here:
        dataRepository.findAll().forEach(a -> cacheManager.getCache("cache-name")).put(a.getKey(), a));
    }

    @Scheduled(fixedRate = 6000)
    public void refreshAllcachesAtIntervals() {
        refreshAllCaches();
    }

}

答案 4 :(得分:0)

除了上述答案外,您还可以在调度程序中使用 cron,这提供了更大的灵活性。您可以让调度程序每天、每周、每年、每天下午 12 点等运行,而无需编写大量代码。

@服务 公共类 CacheService {

@Autowired
CacheManager cacheManager;

public void evictAllCaches() {
    cacheManager.getCacheNames().stream()
      .forEach(cacheName -> cacheManager.getCache(cacheName).clear());
}

@Scheduled(cron = "@weekly")
public void evictAllcachesAtIntervals() {
    evictAllCaches();
}

}

答案 5 :(得分:0)

要求是以X间隔刷新1个缓存,以Y间隔刷新另一个缓存。如果我们只在 1 个类中编写以下代码,则不会重新加载缓存。


public class XXXSchedulers {

    @Autowired
    private XXXUtil util;

    @Scheduled(fixedDelay = 10 * 60 * 1000) // Running after 10 minutes
    public void clearSpecificABCCache() {
        util.clearSpecificABCCache();
        util.getABC();//Again gets value in the cache
    }

    @Scheduled(cron = "0 0 2 * * ?") //Running Everyday at 2 AM public void 
    public void clearSpecificXYZCache() {
        util.clearSpecificABCCache();
        util.getXYZ();
    }
}

@Component
public class XXXUtil {
    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private XXXService service;

    @Cacheable("abc")
    public ABC getABC() {
        ABC abc = service.getABC();
    }

    public void clearSpecificABCCache() {
        cacheManager.getCache("abc").clear();
    }

    @Cacheable("xyz")
    public XYZ getXYZCache() {
        XYZ xyz = service.getXYZCache();
    }
    
    public void clearSpecificXYZCache() {
        cacheManager.getCache("xyz").clear();
    }
  }