如何执行不阻塞且避免高速缓存踩踏的获取/计算查找。
这是一个不会踩踏而是阻塞的示例。
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());
}
这是一个不会阻塞但会踩踏的示例。
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());
}
是否存在不会踩踏或阻止的方法?只在自己的调度程序上订阅阻塞调用是否有意义?
答案 0 :(得分:3)
为重新说明您的问题,您希望避免加盖戳记,同时允许异步执行计算。理想情况下,可以使用带有ConcurrentMap<K, Mono<V>>
的{{1}}和computeIfAbsent
来完成,如果计算失败,它将丢弃该条目。
咖啡因的AsyncLoadingCache
通过使用CompletableFuture<V>
作为值类型来提供这种行为。您可以将阻止功能重写为
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())));
}
从2.6.x版本开始,如果需要,没有更简单的AsyncCache
会收到反馈,它将在2.7版本中发布。这还将包括一个ConcurrentMap<K, CompletableFuture<V>>
视图,该视图使您可以泛化方法,使其不具有提供程序特定的接口。目前,您可以通过避免加载方法并使用Caffeine.newBuilder().buildAsync(key -> null)
来模拟非加载缓存。