当您必须从数据中提供多个结果时,如何最佳地使用 Guava Cache?

问题描述

我有一个缓存加载器,它缓存来自 API 的响应(以列表的形式)。现在我的函数不需要直接响应数据,所以我创建了一个提供程序,它可以处理这些原始响应并充当预言机,允许我发送所需的数据而不是整个列表。

我当前方法的问题是,对于每个这样的响应,即使列表与以前相同,提供者也必须遍历整个列表;这使得每次调用的复杂度为 O(n) 而不是我想要的 O(1)。

我能想到的潜在解决方

  1. 改为缓存已处理的数据。现在的问题是,在这种情况下我需要两个不同的缓存,并且每次刷新都会从 API 中不必要地从两个缓存中获取相同的结果。
  2. 仅在缓存值已更改时才在提供程序中迭代 我想这样做,但我找不到一种方法来知道缓存是否更改了值,我所有的方法都需要传递再次花费 O(n) 时间的数据。

谁能提出解决这个问题的好方法

规则信息缓存加载器类


import com.google.common.cache.CacheLoader;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.ParametersAreNonnullByDefault;

final class RuleInfoLoader extends CacheLoader<RuleType,List<RuleInfo>> {
  private final ConfigServiceGrpc.ConfigServiceBlockingStub configServiceBlockingStub;
  private final long callTimeout;

  RuleInfoLoader(ConfigServiceClientConfig clientConfig) {
    callTimeout = clientConfig.getCallTimeout();
    configServiceBlockingStub = ConfigServiceGrpc.newBlockingStub();
  }

  @Override
  @ParametersAreNonnullByDefault
  public List<RuleInfo> load(RuleType ruleType) {
    return fetchRuleInfo(ruleType);
  }

  private List<RuleInfo> fetchRuleInfo(RuleType ruleType) {
    return configServiceBlockingStub
        .withDeadlineAfter(callTimeout,TimeUnit.MILLISECONDS)
        .getAnomalyRuleInfos(
            GetRuleInfosRequest.newBuilder().setRuleType(ruleType).build())
        .getRuleInfosList();
  }
}

规则信息提供者

import com.google.common.cache.CacheLoader;
import com.google.common.collect.ImmutableMap;
import com.typesafe.config.Config;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

public class RuleInfoProvider {
  private LoadingCache<RuleType,List<RuleInfo>> ruleInfoCache;

  public RuleInfoProvider(Config config) {
    initCache(config);
  }

  public Map<String,RuleInfo> getRuleMapping() {
    ImmutableMap.Builder<String,RuleInfo> mapBuilder = new ImmutableMap.Builder<>();
    getRuleInfo(RuleType.a)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    getRuleInfo(RuleType.b)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    getRuleInfo(RuleType.c)
        .forEach(rule -> mapBuilder.put(rule.getRuleId(),rule));
    return mapBuilder.build();
  }

  public Map<Class<? extends RuleInfo>,List<String>> getPathsMapping() {
    return new ImmutableMap.Builder<Class<? extends RuleInfo>,List<String>>()
        .put(
            Class_A.class,getRuleInfo(RuleType.a).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .put(
            Class_B.class,getRuleInfo(RuleType.b).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .put(
            Class_c.class,getRuleInfo(RuleType.c).stream()
                .map(RuleInfo::getPath)
                .collect(Collectors.toList()))
        .build();
  }

  private List<RuleInfo> getRuleInfo(RuleType ruleType) {
    try {
      return ruleInfoCache.get(ruleType);
    } catch (Exception e) {
      return Collections.emptyList();
    }
  }
  
  private void initCache(Config config) {
    ruleInfoCache =
        CacheBuilder.newBuilder()
            .refreshAfterWrite(config.getCacheConfig().getRefreshMs())
            .maximumSize(config.getCacheConfig().getMaxSize())
            .build(
                CacheLoader.asyncReloading(
                    new RuleInfoLoader(config.getConfigServiceClientConfig()),Executors.newSingleThreadScheduledExecutor()));
  }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...