Ehcache 是否使用后台线程来删除过期项目?

如何解决Ehcache 是否使用后台线程来删除过期项目?

我此时正在使用 guava 缓存,并考虑迁移到 Ehcache。根据这个 post 没有线程确保在番石榴缓存中的延迟过去后立即从缓存中删除条目:

使用 CacheBuilder 构建的缓存不执行清理和驱逐值 “自动”,或在值过期后立即,或任何 那种。相反,它在运行期间执行少量维护 写操作,或者在偶尔的读操作期间,如果写是 罕见。

这样做的原因如下:如果我们要执行Cache 持续维护,我们需要创建一个线程,它的 操作将与用户操作竞争共享锁。 此外,一些环境限制线程的创建, 这将使 CacheBuilder 在该环境中无法使用。

但是 Ehcache 呢?是否有单独的线程在使用内存存储时删除过期项目?我试图寻找信息,但有人说没有,有人说有。

解决方法

TLDR: Ehcache 不提供提示过期。 Guava 清理更迅速,但需要外部调度以保证粗粒度。 Caffeine 可以根据下一个到期事件安排清理。

Ehcache 依靠大小驱逐来丢弃过期的条目。这意味着当需要空间时,尽管缓存中保存了许多过期的死条目,但仍可能会丢弃一个活动条目。由于 Ehcache 使用统一采样来发现驱逐候选,因此它必须偶然发现一个死条目才能考虑将其删除。

在审查 Ehcache 2.x 和 3.x 的实现时,我的理解是两者都更喜欢驱逐过期条目而不是实时条目。采样条目按其 lastAccessTime 字段排序,以便驱逐最近最少使用的条目。如果到期时间不同,例如共享缓存同时包含短期 2FA 令牌和长期数据,那么在等待过期条目老化时可能会浪费大量空间。这种方法反映了 Memcached 和 Redis,但是由于它们非常大,这些缓存使用后台线程来主动查找和删除死条目。

Guava 在 O(1) 优先级队列中维护条目,以便它可以在维护期间删除过期条目,例如在可能需要驱逐的写入之后。这仅实现了固定到期时间,因此可以将条目存储在双向链表中并在恒定时间内重新排序到尾部位置。通过查看列表的头部,Guava 可以立即找到并修剪过期的条目。正如@LouisWasserman 建议的那样,定期调用 Cache.cleanUp() 可确保非活动缓存将检查列表并丢弃过期条目。无论如何,缓存将定期执行维护以响应读取和写入活动。

Caffeine 通过支持 per-entry expirationscheduler 来扩展这种方法,以根据下一个到期事件触发缓存维护。使用 hierarchical timer wheel 在 O(1) 时间内实现变量过期。如果提供了调度线程,则调度任务将执行维护并导致过期条目立即被逐出。在 Java 9+ 中,JVM 包含一个专用的调度线程,如果配置了 Scheduler.systemScheduler(),Caffeine 可以使用该线程。

LoadingCache<Key,Graph> graphs = Caffeine.newBuilder()
    .scheduler(Scheduler.systemScheduler())
    .expireAfterWrite(10,TimeUnit.MINUTES)
    .build(key -> createExpensiveGraph(key));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?