根据时间戳条件删除咖啡因条目

问题描述

有没有办法根据时间戳条件删除咖啡因条目?例如。, 在 T1 我有以下条目

K1 -> V1
K2 -> V2
K3 -> V3

在时间 T2 我只更新 K2K3。 (我不知道两个条目是否都有 exact 时间戳。K2 可能有 T2,但 K3 可能是 T2 + some nanos。但是为了这个问题让我们假设他们这样做)

现在我希望咖啡因使条目 K1 -> V1 无效,因为 T1 < T2

执行此操作的一种方法是迭代条目并检查它们的写入时间戳是否为 T2。收集这些密钥并最终调用 invalidateKeys(keys)

也许有一种非迭代的方式?

解决方法

如果您使用 expireAfterWrite,则可以按时间戳顺序获取条目的快照。由于此调用需要获取驱逐锁,因此它提供了一个不可变的快照而不是迭代器。那很乱,例如您必须提供一个可能不正确的限制,这取决于到期时间。

Duration maxAge = Duration.ofMinutes(1);
cache.policy().expireAfterWrite().ifPresent(policy -> {
  Map<K,V> oldest = policy.oldest(1_000);
  for (K key : oldest.keySet()) {
    // Remove everything written more than 1 minute ago
    policy.ageOf(key)
      .filter(duration -> duration.compareTo(maxAge) > 0)
      .ifPresent(duration -> cache.invalidate(key));
  }
});

如果您自己维护时间戳,则可以使用 cache.asMap() 视图进行无序迭代。这可能是最简单和快速的。

long cutoff = ...
var keys = cache.asMap().entrySet().stream()
  .filter(entry -> entry.getValue().timestamp() < cutoff)
  .collect(toList());
cache.invalidateAll(keys);

一种行不通但值得一提的方法是变量过期,expireAfter(expiry)。您可以根据先前的设置为每次读取设置新的持续时间。这会在条目返回给调用者后生效,因此虽然您可以立即过期,但它将服务 K1(至少)一次。

否则,您可以在缓存之外的检索时间进行验证并依赖大小逐出。这种方法的缺陷在于它确实会污染缓存和死条目。

V value = cache.get(key);
if (value.timestamp() < cutoff) {
  cache.asMap().remove(key,value);
  return cache.get(key); // load a new value
}
return value;

或者您可以维护自己的写入顺序队列等。所有这些都会随着您的喜好而变得混乱。对于您的情况,完整迭代可能是最简单且最不容易出错的方法。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...