Caffeine缓存 – maximumSize驱逐似乎不会延迟

huangapple 未分类评论45阅读模式
英文:

Caffeine cache - maximumSize eviction seems not to be late

问题

我们遇到了关于Caffeine缓存的问题。我们将其配置为大小为60,TTL为300秒,如下所示:

```java
Cache<String, String> cache = Caffeine.newBuilder()
                .expireAfterWrite(300, TimeUnit.SECONDS)
                .maximumSize(60)
                .removalListener((String key, String value, RemovalCause cause) -> {
                    cacheListenerHandler(key, value, cause);
                })
                .build();

现在,removalListener被定义如下:

private void cacheListenerHandler(String key, String value, RemovalCause cause) {
        if (RemovalCause.EXPIRED.equals(cause)) {
            if (value != null) {
                LOG.info("我们获取到了键 {} 和值 {} 的TTL过期",
                        key, value);
            } else {
                LOG.warn("TTL过期时值为空! 键: {}", key);
            }
        }

        if (RemovalCause.SIZE.equals(cause)) {
            if (value != null) {
                LOG.info("我们获取到了键 {} 和值 {} 的SIZE过期",
                        key, value);
                //一些逻辑
            } else {
                LOG.warn("SIZE过期时值为空! 键: {}", key);
            }
        }
    }

说完这些,我们是这样插入缓存的:

public void registerValue(String key, String value) {
        cache.put(key, value);
        LOG.info("键 {} 被添加,值为 {}. 当前缓存中有估计 {} 个键",
                key, value, cache.estimatedSize());
}

问题是有时候我们会得到这样的日志:

> 键 'key1' 被添加,值为 'value1'。当前缓存中有估计 250 个键

然后我们会不断地看到驱逐日志(监听器方法的日志):

> 我们获取到了键 'key1' 和值 'value1' 的SIZE过期

一秒钟后会出现日志:

> 键 'key2' 被添加,值为 'value2'。当前缓存中有估计 251 个键

现在,我知道关于 'estimatedSize' 的细微差别 - 它包括即将被驱逐的键,但问题是我们遇到了Java内存堆问题,这意味着实际的驱逐发生得太晚了,无法使用。

有解决方法吗?也许我们需要转而使用Guava?


<details>
<summary>英文:</summary>

We have an issue with Caffeine cache. We configured it to be of size 60, with TTL of 300 seconds like this:

Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(300, TimeUnit.SECONDS)
.maximumSize(60)
.removalListener((String key, String value, RemovalCause cause) -> {
cacheListenerHandler(key, value, cause);
})
.build();


Now, the removalListener is defined like this:

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(&quot;We got SIZE expiry of key {} and value {}&quot;,
                    key, value);
            //some logic
        } else {
            LOG.warn(&quot;Value is null for SIZE expiry! key: {}&quot;, key);
        }
    }
}

With that being said, we insert to the cache this way:

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());
}


The issue is that sometimes we get logs such as:

&gt; Key &#39;key1&#39; was added with value &#39;value1&#39;. Current estimated size of 250 keys in cache

And we see constantly the eviction logs (of the listener method):

&gt; We got SIZE expiry of key &#39;key1&#39; and value &#39;value1&#39;

And a second later the log:

&gt; Key &#39;key2&#39; was added with value &#39;value2&#39;. Current estimated size of 251 keys in cache

Now, I know about the &#39;estimatedSize&#39; nuance - it includes the keys that are going to be evicted, but the issue is that we get Java memory heap issues, meaning the actual removal happens too late for use.

Is there a solution for it? Maybe we need to switch to Guava instead?

</details>


huangapple
  • 本文由 发表于 2020年4月6日 22:13:40
  • 转载请务必保留本文链接:https://java.coder-hub.com/61061826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定