gpt4 book ai didi

java - 如何可靠地从 Guava LoadingCache 中删除记录?

转载 作者:行者123 更新时间:2023-12-02 03:10:30 27 4
gpt4 key购买 nike

我正在使用 Guava LoadingCache 向其中填充一些数据,并且我想每 1 分钟从该 LoadingCache 中删除所有条目。

public class MetricHolder {
private final ExecutorService executor = Executors.newFixedThreadPool(2);
private final LoadingCache<String, AtomicLongMap<String>> clientIdMetricCounterCache =
CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES)
.removalListener(RemovalListeners.asynchronous(new SendToDatabase(), executor))
.build(new CacheLoader<String, AtomicLongMap<String>>() {
@Override
public AtomicLongMap<String> load(String key) throws Exception {
return AtomicLongMap.create();
}
});

private static class Holder {
private static final MetricHolder INSTANCE = new MetricHolder();
}

public static MetricHolder getInstance() {
return Holder.INSTANCE;
}

private MetricHolder() {}

public void increment(String clientId, String name) throws ExecutionException {
clientIdMetricCounterCache.get(clientId).incrementAndGet(name);
}

public LoadingCache<String, AtomicLongMap<String>> getClientIdMetricCounterCache() {
return clientIdMetricCounterCache;
}

private static class SendToDatabase implements RemovalListener<String, AtomicLongMap<String>> {
@Override
public void onRemoval(RemovalNotification<String, AtomicLongMap<String>> notification) {
String key = notification.getKey();
AtomicLongMap<String> value = notification.getValue();
System.out.println(key);
System.out.println(value);
// sending these key/value to some other system

}
}
}

我正在以多线程方式从代码中的许多不同位置调用increment方法。因此,在 1 分钟的时间内,它将在 clientIdMetricCounterCache 中填充大量指标。现在,我想每 1 分钟后可靠删除所有这些指标,并将所有这些指标发送到数据库。

就我而言,有时写入 increment 方法可能会非常慢,但我仍然想每 1 分钟删除所有这些条目,并且我根本没有对此缓存进行任何读取,只是写入然后通过发送到其他系统来删除这些记录。下面是我在Guava看到的wiki

Caches built with CacheBuilder do not perform cleanup and evict values "automatically," or instantly after a value expires, or anything of the sort. Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.

那么expireAfterWrite是如何工作的呢?它是否像调度程序一样工作,每 1 分钟运行一次并删除 clientIdMetricCounterCache 中的所有条目,然后它会在 1 分钟后再次唤醒并删除同一缓存中的所有条目并保留就这样吗?读完维基百科后,我怀疑它是这样工作的。如果没有,那么我怎样才能可靠地每 1 分钟删除这些记录并发送到其他系统,因为我的写入在一段时间内可能很少见?

看起来我可能必须使用 Guava TimeLimiter 接口(interface)和 SimpleTimeLimiter 或者可能是 ScheduledExecutorService 来可靠地使调用超时,然后删除条目?如果是,任何人都可以提供一个示例,这在我当前的示例中将如何工作?

最佳答案

对我来说,您似乎滥用了缓存,而 map 就可以做到这一点。您没有使用过期时间、没有大小限制、没有缓存,您只是在收集统计信息。

您使用的唯一功能是加载方面,这并不值得。

我建议使用AtomicReference<ConcurrentHashMap<String, AtomicLongMap>>相反:

  • 更新时,您可以通过 AtomicReference::get 获取当前分钟的版本.
  • 使用clientId ,您查找 AtomicLongMap在你的ConcurrentHashMap如果未找到,则创建一个新的(在 Java 7 上使用 putIfAbsent 或在 Java 8 上使用 computeIfAbsent)。
  • 使用name ,您更新AtomicLongMap就像您发布的那样。
  • 每分钟一次,您可以通过 AtomicReference::getAndSet 更换所有内容.

通过更换,您可以确保您的统计数据不会干扰,但是,您应该在getAndSet之后稍等一下。因为可能有线程刚刚获得引用并即将写入。

它会比原来的方法产生更多的垃圾,但所有的垃圾都是短暂的,所以你实际上可能会让 GC 更快乐。

它很简单,不需要深入了解库或其实现细节。

<小时/>

我猜,volatile而不是AtomicReference也可以。

关于java - 如何可靠地从 Guava LoadingCache 中删除记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41113560/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com