我知道Guava Cache允许为个人缓存配置一个到期时间。 Guava是否使用在配置的秒数后唤醒的计时器来使缓存失效?
我有一个长期运行的交易。无论交易开始时缓存中有什么,我希望它能一直持续到交易结束。因此,即使在事务期间缓存的有效秒数达到过期,从缓存访问的值也应保持不变,直到我们到达事务结束。这可能在番石榴中吗?
谢谢,
佳日
答案 0 :(得分:2)
来自When Does Cleanup Happen? · CachesExplained · google/guava Wiki:
使用
CacheBuilder
构建的缓存不执行清理并逐出值 “自动”,或在值到期后立即或任何其他内容 那种。相反,它在执行期间执行少量维护 写入操作,或者在写入时偶尔进行读取操作 罕见的。原因如下:如果我们想要执行
Cache
维护不断,我们需要创建一个线程,它的 操作将与共享锁的用户操作竞争。 此外,某些环境限制线程的创建, 这将使CacheBuilder
在该环境中无法使用。相反,我们将选择权交给您。如果您的缓存是 高吞吐量,那么你不必担心执行缓存 维护以清理过期的条目等。如果你的缓存 写入很少,你不希望清理阻止缓存 读取,您可能希望创建自己的调用维护线程
Cache.cleanUp()
定期。{/ p>如果要为缓存安排常规缓存维护 只有很少写入,只需使用安排维护
ScheduledExecutorService
因此,如果您只是在阅读时,如果您在交易之前和之后进行Cache.cleanUp()
,那么“可能”会很好,但仍无法保证。
但是,不是试图强制项目留在缓存中,而是使用removalListener
简单地将项目驱逐到另一个缓存/地图,然后在阅读时首先需要检查缓存,然后,如果不存在,请检查长期交易中被驱逐的物品。
以下是一个过于简单的例子:
Map<Integer, String> evicted = new ConcurrentHashMap<>();
Cache<Integer, String> cache = CacheBuilder.newBuilder()
.expireAfterAccess(2, SECONDS)
.removalListener((RemovalListener<Integer, String>) notification ->
evicted.put(notification.getKey(), notification.getValue()))
.build();
assert evicted.size() == 0 && cache.size() == 0;
cache.put(0, "a");
cache.put(1, "b");
cache.put(2, "c");
assert evicted.size() == 0 && cache.size() == 3;
sleepUninterruptibly(1, SECONDS);
assert evicted.size() == 0 && cache.size() == 3;
cache.put(3, "d");
assert evicted.size() == 0 && cache.size() == 4;
sleepUninterruptibly(1, SECONDS);
cache.cleanUp();
assert evicted.size() == 3 && cache.size() == 1;
Integer key = 2;
String value;
{
value = cache.getIfPresent(key);
if (value == null) value = evicted.get(key);
}
assert Objects.equals(value, "c");
您的实际代码需要有条件地put
进入evicted
,清理evicted
,如果您同时运行长时间运行的事务或管理多个evicted
对象具有不同驱逐策略的线程之间的公共缓存等等,但希望这充分证明了这个想法可以帮助您入门。