EhCache 3.10.8在Spring Boot中缓存条目未按TTL过期问题排查
问题
我正在使用EhCache 3.10.8和SpringBoot 2.4.0,通过Spring Bean配置了TTL为30秒的缓存。使用@Cacheable注解的方法填充缓存条目,但条目过了约5分钟仍未被驱逐。请问该Bean定义是否正确?如何确保缓存按配置的TTL过期?
build.gradle
//Caching implementation 'org.springframework.boot:spring-boot-starter-cache:2.7.0' implementation 'javax.cache:cache-api:1.1.1' implementation 'org.ehcache:ehcache:3.10.8'
CacheConfig
package com.example.application.config; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.jsr107.Eh107Configuration; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.cache.CacheManager; import javax.cache.Caching; import javax.cache.spi.CachingProvider; import java.time.Duration; @Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager ehCacheManager() { CachingProvider provider = Caching.getCachingProvider(); CacheManager cacheManager = provider.getCacheManager(); CacheConfigurationBuilder<String, Boolean> configuration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, Boolean.class, ResourcePoolsBuilder .newResourcePoolsBuilder().offheap(5, MemoryUnit.MB)) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(30))); javax.cache.configuration.Configuration<String, Boolean> cacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(configuration); cacheManager.createCache("isUrlVerified", cacheConfiguration); return cacheManager; } }
@Cacheable使用示例
@Cacheable(value = "isUrlVerified", key = "#url") public Boolean verifyUrl(String url) { //调用其他服务验证URL有效性的代码 }
解决方案
问题分析
- 依赖版本冲突:你使用Spring Boot 2.4.0,但引入的
spring-boot-starter-cache是2.7.0,版本不匹配会导致缓存配置逻辑异常,这是TTL不生效的核心原因之一。 - JCache默认行为限制:EhCache通过JSR-107集成时,默认不会主动驱逐过期条目,仅在缓存条目被访问时才会检查过期状态,或者需要手动配置主动清理调度。
修复步骤
- 统一Spring Boot依赖版本
将spring-boot-starter-cache的版本改为与Spring Boot主版本一致的2.4.0,避免依赖冲突:
//Caching implementation 'org.springframework.boot:spring-boot-starter-cache:2.4.0' implementation 'javax.cache:cache-api:1.1.1' implementation 'org.ehcache:ehcache:3.10.8'
- 启用EhCache主动过期清理
在缓存配置中添加执行服务配置,让EhCache定期主动清理过期条目:
修改CacheConfig中的缓存配置代码,添加withService调用:
CacheConfigurationBuilder<String, Boolean> configuration = CacheConfigurationBuilder.newCacheConfigurationBuilder( String.class, Boolean.class, ResourcePoolsBuilder .newResourcePoolsBuilder().offheap(5, MemoryUnit.MB)) .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(30))) .withService(new DefaultExecutionServiceConfiguration()); // 启用主动过期清理
同时导入对应的类:
import org.ehcache.core.config.DefaultExecutionServiceConfiguration;
- 确保Spring使用自定义CacheManager
在application.properties中添加配置,明确指定缓存类型为JCache,避免Spring自动加载默认缓存管理器:
spring.cache.type=jcache
额外验证建议
- 可以通过调用
cacheManager.getCache("isUrlVerified").get("testUrl")验证过期条目是否被清理,或者在verifyUrl方法中添加日志,观察缓存命中情况。 - 若偏好XML配置方式,也可以在classpath下创建
ehcache.xml文件配置TTL和清理策略,Spring Boot会自动加载该配置。
内容的提问来源于stack exchange,提问作者Prateek Deshpande
相关产品推荐
相关产品推荐

