You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Guava Cache不同Key设置独立refreshAfterWrite时间?

单CacheLoader实现多Key独立刷新方案

完全可以通过单个CacheLoader实现你的需求,核心是用带类型标识的缓存Key区分两个集合,结合定时任务触发不同Key的异步刷新,同时保证单次API调用即可更新两个缓存项。以下是具体实现:

1. 定义区分类型的缓存Key

先创建枚举标识两种交易集合,再封装成缓存Key:

enum TransactionCacheType {
    ALLOWED, DENIED
}

record TransactionCacheKey(TransactionCacheType type) {}

2. 实现单CacheLoader加载完整数据

CacheLoader的load方法只调用一次API获取完整的Transactions对象,同时更新两个缓存项;reload方法复用加载逻辑,保证异步刷新时也是单次API调用:

public class TransactionsDetailsCacheLoader extends CacheLoader<TransactionCacheKey, Set<String>> {

    private final LoadingCache<TransactionCacheKey, Set<String>> cache;
    private final TransactionApiClient apiClient;

    // 构造函数注入缓存实例和API客户端
    public TransactionsDetailsCacheLoader(LoadingCache<TransactionCacheKey, Set<String>> cache, TransactionApiClient apiClient) {
        this.cache = cache;
        this.apiClient = apiClient;
    }

    @Override
    public Set<String> load(TransactionCacheKey key) throws Exception {
        // 单次API调用拉取完整数据
        Transactions transactions = apiClient.fetchAllTransactions();
        
        // 同时更新两个缓存项,保证数据一致性
        cache.put(new TransactionCacheKey(TransactionCacheType.ALLOWED), transactions.getAllowedTransactions());
        cache.put(new TransactionCacheKey(TransactionCacheType.DENIED), transactions.getDeniedTransactions());
        
        // 返回当前请求Key对应的集合
        return switch (key.type()) {
            case ALLOWED -> transactions.getAllowedTransactions();
            case DENIED -> transactions.getDeniedTransactions();
        };
    }

    @Override
    public ListenableFuture<Set<String>> reload(TransactionCacheKey key, Set<String> oldValue) {
        // 复用load逻辑,异步刷新时同样单次API调用更新两个缓存
        return Futures.immediateFuture(load(key));
    }
}

3. 初始化缓存与定时刷新任务

不设置全局refreshAfterWrite,而是通过定时任务分别控制两个Key的异步刷新间隔,同时配置兜底过期时间防止任务异常:

// 初始化缓存:设置兜底过期时间(比刷新间隔略长即可)
LoadingCache<TransactionCacheKey, Set<String>> transactionCache = CacheBuilder.newBuilder()
        .expireAfterWrite(1, TimeUnit.HOURS) // 兜底:1小时未刷新则过期
        .build(new TransactionsDetailsCacheLoader(transactionCache, apiClient));

// 初始化定时任务池
ScheduledExecutorService refreshScheduler = Executors.newSingleThreadScheduledExecutor();

// 配置ALLOWED Key的刷新:每1小时一次
refreshScheduler.scheduleAtFixedRate(
        () -> transactionCache.refresh(new TransactionCacheKey(TransactionCacheType.ALLOWED)),
        0, // 首次立即执行
        1,
        TimeUnit.HOURS
);

// 配置DENIED Key的刷新:每5分钟一次
refreshScheduler.scheduleAtFixedRate(
        () -> transactionCache.refresh(new TransactionCacheKey(TransactionCacheType.DENIED)),
        0,
        5,
        TimeUnit.MINUTES
);

4. 缓存使用方式

通过对应Key直接获取目标集合:

// 获取允许的交易集合
Set<String> allowedTransactions = transactionCache.get(new TransactionCacheKey(TransactionCacheType.ALLOWED));

// 获取拒绝的交易集合
Set<String> deniedTransactions = transactionCache.get(new TransactionCacheKey(TransactionCacheType.DENIED));

核心优势

  • 单CacheLoader实现,无需拆分缓存,保证API调用只触发一次
  • 两个Key独立配置刷新间隔,满足1小时和5分钟的需求
  • 异步刷新不阻塞业务请求,同时兜底过期时间避免缓存失效

内容的提问来源于stack exchange,提问作者Logic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:06:13