我们遇到了咖啡因缓存的问题。我们将它的大小配置为 60,TTL 为 300 秒,如下所示:
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(300, TimeUnit.SECONDS)
.maximumSize(60)
.removalListener((String key, String value, RemovalCause cause) -> {
cacheListenerHandler(key, value, cause);
})
.build();
现在,removingListener 的定义如下:
private void cacheListenerHandler(String key, String value, RemovalCause cause) {
if (RemovalCause.EXPIRED.equals(cause)) {
if (value != null) {
LOG.info("We got TTL expiry of key {} and value {}",
key, value);
} else {
LOG.warn("Value is null for TTL expiry! key: {}", key);
}
}
if (RemovalCause.SIZE.equals(cause)) {
if (value != null) {
LOG.info("We got SIZE expiry of key {} and value {}",
key, value);
//some logic
} else {
LOG.warn("Value is null for SIZE expiry! key: {}", key);
}
}
}
话虽如此,我们以这种方式插入缓存:
public void registerValue(String key, String value) {
cache.put(key, value);
LOG.info("Key {} was added with value {}. Current estimated size of {} keys in cache",
key, value, cache.estimatedSize());
}
问题是有时我们会得到以下日志:
键 'key1' 添加了值 'value1'。当前估计缓存中 250 个键的大小
我们经常看到驱逐日志(监听器方法):
我们得到键“key1”和值“value1”的大小到期
一秒钟后,日志:
键 'key2' 添加了值 'value2'。当前估计缓存中 251 个键的大小
现在,我知道了“estimatedSize”的细微差别——它包括将要被驱逐的键,但问题是我们遇到了 Java 内存堆问题,这意味着实际删除发生得太晚而无法使用。
有解决办法吗?也许我们需要改用番石榴?