У нас проблема с кофеином. Мы настроили его на размер 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();
Теперь, RemovalListener определен так:
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 ключей в кеше
И мы постоянно видим журналы выселения (метода слушателя):
Мы получили SIZE истечение срока ключа 'key1' и значение 'value1'
И через секунду в журнал:
Ключ 'key2' был добавлен со значением 'value2'. Текущий примерный размер 251 ключа в кеше
Теперь я знаю о нюансе'timateSize '- он включает в себя ключи, которые будут удалены, но проблема в том, что мы получаем Java памяти проблемы кучи, означающие, что фактическое удаление происходит слишком поздно для использования.
Есть ли решение для этого? Может быть, вместо этого нам нужно перейти на Guava?