英文:
Spring WebFlux with in memory cache
问题
我正在使用 Spring WebFlux 和 Guava 缓存。在一些示例中,他们使用 CacheMono.lookup 来从缓存中检索值。我按照相同的思路尝试了以下代码。
CacheMono.lookup(key -> Mono.justOrEmpty(guavaCache.get(id, PhoneNumber.class))
.map(Signal::next), id)
.onCacheMissResume(() -> {
LOGGER.info("fetch from db");
return phoneNumberRepository.findById(id);})
.andWriteWith((key, signal) -> Mono.fromRunnable(() ->
Optional.ofNullable(signal.get())
.ifPresent(value -> {
if(value == null){
LOGGER.info("value is null");
}
LOGGER.info("value is not null " + value);
guavaCache.put(key, value);}))))
对于初始流程,当 Guava 缓存不包含该值时,它会从数据库中获取并存储到缓存中。但是对于相同的键(key),当我再次发送请求时,缓存中已经有了该键的值。但是 CacheMono.lookup 仍然在执行从数据库中获取的操作(我看到了 LOGGER.info("fetch from db");)。但同时我没有看到日志 LOGGER.info("value is not null " + value); 我对这种行为感到困惑。为什么当缓存已经有数据时,onCacheMissResume 会第二次被调用呢?
英文:
I am using Spring web flux and guava cache. In some of the examples they are using CacheMono.lookup to retrieve the value from the cache. I tried on the same lines and have following code.
CacheMono.lookup(key -> Mono.justOrEmpty(guavaCache.get(id, PhoneNumber.class))
.map(Signal::next), id)
.onCacheMissResume(() -> {
LOGGER.info("fetch from db");
return phoneNumberRepository.findById(id);})
.andWriteWith((key, signal) -> Mono.fromRunnable(() ->
Optional.ofNullable(signal.get())
.ifPresent(value -> {
if(value == null){
LOGGER.info("value is null");
}
LOGGER.info("value is not null "+value);
guavaCache.put(key, value);}))))
For the initial flow when guava cache does not contain the value it is fetching from db and storing into the cache. But for the same key when I send the request again, the cache has the value for the key. But CacheMono.lookup is still executing the fetch from db ( I am seeing LOGGER.info("fetch from db");.
But at the same time I am not seeing the logs LOGGER.info("value is not null "+value);
I am confused with this behavior. Why onCacheMissResume is called 2nd time when the cache has the data already.
答案1
得分: 3
你看到 LOGGER.info("fetch from db")
是因为每当 CacheMono
创建 Mono<PhoneNumber>
从数据库中获取数据时,都会调用它。但是如果缓存中存在该值,则不会订阅此 Mono<PhoneNumber>
。
您可以通过记录 onSubscribe
事件来进行检查:
.onCacheMissResume(() -> {
LOGGER.info("fetch from db");
return phoneNumberRepository.findById(id)
.doOnSubscribe(ignored -> LOGGER.info("really fetching from db"));
})
英文:
You see LOGGER.info("fetch from db")
because it is called every time CacheMono
creates Mono<PhoneNumber>
to fetching from db. But this Mono<PhoneNumber>
won't be subscribed if the value exists in your cache.
You could examine it with logging onSubscribe
event:
.onCacheMissResume(() -> {
LOGGER.info("fetch from db");
return phoneNumberRepository.findById(id)
.doOnSubscribe(ignored -> LOGGER.info("really fetching from db"));
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论