我正在使用 Caffeine v2.8.5,我想创建一个具有可变到期时间的缓存,基于:
无论先发生什么都应该触发该条目的删除。
缓存将成为三层值解析的一部分:
- The key is present in the Caffeine cache
- The key is present in the Redis database
- 使用这个值
- 将此值与剩余的值一起存储在咖啡因缓存中TTL(生存时间) https://redis.io/commands/ttlRedis 密钥的
- The key was neither present in the internal cache nor Redis
- 从外部 REST API 请求值
- 将此值存储在 Redis 数据库中,固定期限为 30 天
- 将此值存储在 Caffeine 缓存中,固定期限为 30 天
Redis用作全局缓存,以便多个应用程序/实例可以共享缓存数据,但这种解析经常发生,以至于它不能用于每个请求,因此需要另一个缓存层。
根据请求时间,请求的数据具有不同的 TTL。因此,虽然当我们请求 REST API 时过期时间可能是固定的,并且过期时间是在 Redis 中设置的,但在 Caffeine 中该时间将是动态的,因为过期时间基于 Redis 密钥的剩余 TTL。
情况 (2) 和 (3) 已经在我的 Caffeine 缓存的 CacheLoader 中得到解决(我在通读模式下使用缓存)。为了控制我已经发现的过期时间,我必须利用高级过期 API https://github.com/ben-manes/caffeine/wiki/Eviction#time-based我也研究过类似的问题(指定条目的到期时间) https://stackoverflow.com/questions/51779879/caffeine-how-expires-cached-values-only-after-creation-time and (缓存值在创建时间后过期) https://stackoverflow.com/questions/51779879/caffeine-how-expires-cached-values-only-after-creation-time。所以我为我的键想出了一个包装对象,如下所示:
import lombok.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
@Value
public class ExpiringValue<ValueType> {
@Nullable
private final ValueType value;
@NotNull
private final Instant validUntil;
}
and an Expiry https://www.javadoc.io/doc/com.github.ben-manes.caffeine/caffeine/2.5.2/com/github/benmanes/caffeine/cache/Expiry.html像这样:
import com.github.benmanes.caffeine.cache.Expiry;
import org.jetbrains.annotations.NotNull;
import java.time.Duration;
import java.time.Instant;
public final class ValueBasedExpiry<KeyType, ValueType extends ExpiringValue<?>> implements Expiry<KeyType, ValueType> {
@Override
public long expireAfterCreate(
@NotNull final KeyType key,
@NotNull final ValueType value,
final long currentTime
) {
return Duration.between(Instant.now(), value.getValidUntil()).toNanos();
}
@Override
public long expireAfterUpdate(
@NotNull final KeyType key,
@NotNull final ValueType value,
final long currentTime,
final long currentDuration
) {
return currentDuration;
}
@Override
public long expireAfterRead(
@NotNull final KeyType key,
@NotNull final ValueType value,
final long currentTime,
final long currentDuration
) {
return currentDuration;
}
}
我的用例的不同之处在于,我希望有一个基于该值的最后一次访问的第二个到期标准。因此,如果一个小时内没有提出请求,我想提前删除该条目。而如果频繁访问,最终会在 TTL 为零后被删除。
我将如何实施第二个标准?我不知道如何获取上次访问条目的时间。该接口似乎没有提供这样的值。我也调查过这个问题 https://stackoverflow.com/questions/62998616/caffeine-cache-delayed-entries-expiration-with-after-creation-policy。根据条目已排序到的调度程序存储桶,定期调用/重新评估这些方法是否正确?