Spring WebFlux与内存缓存

huangapple go评论145阅读模式
英文:

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(&quot;fetch from db&quot;) because it is called every time CacheMono creates Mono&lt;PhoneNumber&gt; to fetching from db. But this Mono&lt;PhoneNumber&gt; won't be subscribed if the value exists in your cache.

You could examine it with logging onSubscribe event:

.onCacheMissResume(() -&gt; {
    LOGGER.info(&quot;fetch from db&quot;);
    return phoneNumberRepository.findById(id)
        .doOnSubscribe(ignored -&gt; LOGGER.info(&quot;really fetching from db&quot;));
})

huangapple
  • 本文由 发表于 2020年9月9日 21:05:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63812343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定