Java 8 如何在ProjectReactor中缓存项并避免缓存抢占?

Java 8 如何在ProjectReactor中缓存项并避免缓存抢占?,java-8,project-reactor,caffeine,Java 8,Project Reactor,Caffeine,如何执行非阻塞的get/compute查找并避免缓存阻塞 public static <KEY, VALUE> MonoCacheBuilderCacheMiss<KEY, VALUE> lookup( Function<KEY, Mono<Signal<? extends VALUE>>> reader, KEY key) { return otherSupplier -> writer -> Mo

如何执行非阻塞的get/compute查找并避免缓存阻塞

public static <KEY, VALUE> MonoCacheBuilderCacheMiss<KEY, VALUE> lookup(
        Function<KEY, Mono<Signal<? extends VALUE>>> reader, KEY key) {
    return otherSupplier -> writer -> Mono.defer(() ->
            reader.apply(key)
                    .switchIfEmpty(otherSupplier.get()
                            .materialize()
                            .flatMap(signal -> writer.apply(key, signal)
                            )
                    )
                    .dematerialize());
}
下面是一个不会踩踏的示例,但它是阻塞的

public static <KEY, VALUE> Mono<VALUE> lookupAndWrite(
    Map<KEY, Signal<? extends VALUE>> cacheMap, KEY key, Mono<VALUE> mono) {
    return Mono.defer(() -> Mono.just(cacheMap.computeIfAbsent(key, k -> 
        mono.materialize().block())).dematerialize());
}
公共静态Mono查找和写入(

Map要重新表述您的问题,您希望在允许异步执行计算时避免踩踏。这最好使用
ConcurrentMap
computeFabSent
来完成,如果计算失败,它将丢弃条目

咖啡因的
AsyncLoadingCache
通过使用
CompletableFuture
作为值类型来提供这种行为。您可以将阻塞函数重写为

public static <KEY, VALUE> Mono<VALUE> lookupAndWrite(
    AsyncLoadingCache<KEY, VALUE> cache, KEY key, Mono<VALUE> mono) {
  return Mono.defer(() -> Mono.fromFuture(cache.get(key, (k,e) ->
            mono.subscribeOn(Schedulers.fromExecutor(e)).toFuture())));
}
公共静态Mono查找和写入(
AsyncLoadingCache缓存,密钥,单声道){
返回Mono.defer(()->Mono.fromFuture(cache.get(key,(k,e)->
mono.subscribeOn(Schedulers.fromExecutor(e)).toFuture();
}

从2.6.x版开始,如果需要,没有更简单的
AsyncCache
来听取反馈,它将出现在2.7版本中。这还将包括
ConcurrentMap
视图,该视图允许您将方法概括为没有特定于提供程序的接口。现在,您可以通过避免加载方法来模拟非加载缓存使用
caffee.newBuilder().buildAsync(key->null)

在这里使用
AsyncLoadingCache
有意义吗?这样在计算过程中就不会阻塞,缓存会在未来值完成时添加回调(成功或错误)。(p.S.
AsyncCache
将在下一版本中,但很容易模拟)@BenManes我不确定。密钥没有包含足够的信息来知道如何加载数据(可能这并不重要)。您可以避免
get(key)
调用,让加载程序抛出异常,降级为临时
AsyncCache
。然后您可以用与
cache.get>类似的方式编写代码(key,k->mono.toFuture())
既然这样不适合讨论,如果您愿意,我们可以把它带回您的网站。@BenManes,如果您认为这是最好的。我在这里提出这个问题是希望得到更多的关注,因为这似乎是一个非常常见的问题,尚未提出(对于这个框架)。谢谢您,先生,是否有任何方法可以控制是否缓存出错的Mono。不,作为同步
ConcurrentMap
不会缓存异常或空值,异步缓存将来也会这样做。如果您想要负缓存,则转换为可查询的成功结果,例如
Mono
。该方法请参阅ms使混乱最少,保持接口一致,并且不会使用不同的处理策略使缓存复杂化。