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

Ehcache 2.10.4缓存对象数量查询及过期驱逐失效问题排查

解决Ehcache 2.10.4缓存过期/驱逐失效及对象数量统计问题

先聚焦你的核心问题——缓存未执行过期/驱逐操作来分析,顺便确认对象数量的正确获取方式:

一、先排查缓存过期配置的参数对应错误

看你的枚举定义:

FAILED_MESSAGES_REPLAY_COUNTS("msgreplaycount", 50000, false, 0, 3600)

而你提到缓存项应仅保留300秒,但你的构造方法参数顺序是(name, maxElementsInMemory, eternal, timeToLiveSeconds, timeToIdleSeconds)——这里你传的timeToLiveSeconds是0(永不过期),timeToIdleSeconds是3600(1小时),和你期望的300秒完全不匹配!

在Ehcache 2.x中:

  • timeToLiveSeconds:对象从创建到过期的总时长(0表示永不过期)
  • timeToIdleSeconds:对象多久未被访问就过期(0表示永不过期)

你当前的配置意味着:缓存项只要被创建,就会一直存在(因为TTL设为0),同时你的maxElementsInMemory=50000,而当前缓存大小才317,远没达到内存上限,所以驱逐逻辑也不会触发,这就导致所有缓存项一直留在内存里。

修正配置

如果你期望缓存项300秒后不管是否被访问都过期,应该把timeToLiveSeconds设为300,timeToIdleSeconds按需调整(比如设为0):

FAILED_MESSAGES_REPLAY_COUNTS("msgreplaycount", 50000, false, 300, 0)

如果是期望300秒未访问就过期,那调整timeToIdleSeconds=300,同时确保timeToLiveSeconds设为一个大于空闲时间的值(比如600),避免TTL限制提前生效。

二、理解Ehcache过期机制的触发逻辑

即使配置正确,Ehcache的过期也不是实时触发的,它有两种清理逻辑:

  • 访问时主动检查:当你调用缓存的get方法时,Ehcache会自动检查目标对象是否过期,若过期则立即移除并返回null
  • 后台线程定期清理:Ehcache默认会启动一个后台线程,每120秒扫描一次缓存,清理过期条目。你可以通过配置调整这个间隔:
Cache cache = new Cache(name, maxElementsInMemory, false, eternal, timeToLiveSeconds, timeToIdleSeconds);
cache.setDiskExpiryThreadIntervalSeconds(60); // 改为每60秒清理一次
cm.addCache(cache);

如果你的缓存项很少被访问,可能需要等待后台线程运行后,才能看到expired计数增长。

三、缓存对象数量的正确获取方式

你当前用statistics.getSize()是完全正确的,这个方法会返回缓存中当前存活的条目数量。另外也可以直接调用cache.getSize(),在Ehcache 2.x中两者效果一致,都是返回实时的缓存条目数。

需要注意的是,统计功能默认是开启的,你的代码没有显式关闭,所以统计数据是准确的。

四、验证修正后的效果

修改配置后,你可以通过以下方式验证:

  • 手动写入几个缓存项,等待300秒后尝试读取,看是否返回null(说明过期被移除)
  • 间隔一段时间后查看expired计数是否增长
  • 等待后台清理线程运行后,观察current size是否下降

内容的提问来源于stack exchange,提问作者markthegrea

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:28:28