我正在使用Spring Boot,并且为了缓存我正在使用Ehcache。到目前为止,一切正常。但是现在我必须重新加载/刷新,以便如何执行此操作,以使我的应用程序不会出现任何停机时间。
我已经在Spring Ehcache中尝试了许多方法,但是没有用,否则,其他人必须编写调度程序并重新加载数据。
@Override
@Cacheable(value="partTypeCache", key="#partKey")
public List<PartType> loadPartType(String partKey) throws CustomException {
return productIdentityDao.loadPartType();
}
答案 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();
}
}