Spring Boot 应用程序启动时清空 Redis 缓存

4

在应用程序(Spring Boot服务)启动时,需要清除Redis缓存。

Redis运行在不同的Docker容器中,并具有自己的卷映射。因为它保留了旧的缓存,所以即使应用程序重新启动,它也会从Redis缓存中获取数据而不是数据库。

  • Tried @EventListener for ContextRefreshedEvent and it is never getting called.
  • Tried with @PostConstruct in ApplicationMain class, but it doesn't clear the cache.
  • Tried using @CacheEvict(allEntries = true), but still no luck

    @Component public class ApplicationStartUp {

    @Autowired
    private CacheManager cacheManager;
    
    @EventListener()
    public void onApplicationEvent(ContextStartedEvent event) {
        cacheManager.getCacheNames()
                    .parallelStream()
                    .forEach(n -> cacheManager.getCache(n).clear());
    }
    

    }


你是否验证了 onApplicationEvent 是否被触发,并且在循环中能够获取缓存值? - MyTwoCents
如果您打印cacheManager.getCacheNames()的结果,您能看到缓存名称吗?在启动时,缓存管理器可能不会返回任何内容。作为测试,请尝试使用@PostConstructcacheManger.getCache("your cache").clear() - chrsblck
3个回答

5

我成功地通过ApplicationReadyEvent清除了缓存。由于CacheManager bean在此时已经可用,因此在启动时缓存得到了正确清除。

@Autowired
private CacheManager cacheManager;

@EventListener
public void onApplicationEvent(ApplicationReadyEvent event) {
    cacheManager.getCacheNames()
                .parallelStream()
                .forEach(n -> cacheManager.getCache(n).clear());
}

请问您能提供一下您的缓存配置类吗?我正在实现类似的功能,但仍然遇到了一些问题。 - Loren
你是否获取到了所有缓存数据?因为cacheManager.getCacheNames()不会返回缓存数据。你是如何获取的? - Roul
@senthil cacheManager.getCacheNames() 返回空数据。你是怎么做的?我用的是同样的代码。 - oldcode

4
一个简单的实践是在 Redis 数据库早期生命周期阶段清除数据。为了配置 CacheManager @bean,需要传递 RedisConnectionFactory 参数并调用 flushDb() 方法来删除当前所选数据库的所有键,然后开始构建。
 @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        redisConnectionFactory.getConnection().flushDb(); //Delete all keys of the currently selected database
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()).build();
    }

2

对于 Redis 缓存管理器,如果您想在启动时清除缓存,我认为您需要使用一组名称初始化缓存管理器。请参见RedisCacheManagerBuilder 文档

例如:

RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory)
                        .initialCacheNames(Set.of("cacheOne", "cacheTwo"))
                        .build();

那么您应该能够在缓存配置类中使用@PostConstruct,例如。
@PostConstruct
public void clearCache() {
    cacheManager.getCacheNames()
                .parallelStream()
                .forEach(n -> cacheManager.getCache(n).clear());
}

谢谢您的建议。但我把ContextRefreshedEvent监听器改成了ApplicationReadyEvent监听器,现在它可以正常工作了。 - Senthil
@Senthil 很酷,感谢您也发布了您的解决方案。 - chrsblck
在不初始化缓存名称的情况下,是否可以清除缓存? - Roul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接