You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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有效性的代码
}
解决方案

问题分析

  1. 依赖版本冲突:你使用Spring Boot 2.4.0,但引入的spring-boot-starter-cache是2.7.0,版本不匹配会导致缓存配置逻辑异常,这是TTL不生效的核心原因之一。
  2. JCache默认行为限制:EhCache通过JSR-107集成时,默认不会主动驱逐过期条目,仅在缓存条目被访问时才会检查过期状态,或者需要手动配置主动清理调度。

修复步骤

  1. 统一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'
  1. 启用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;
  1. 确保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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:25:07