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

Spring缓存:如何将@Cacheable结果存入多个缓存?

实现单次查询同时存入双缓存的方案

当然可以实现单次调用慢服务后,将结果同时存入两个缓存。下面提供两种基于Spring Cache的可行方案,完美匹配你的需求:

方案一:手动操作CacheManager

通过Spring的CacheManager直接控制缓存写入,在获取到慢服务结果后,主动将数据存入两个缓存空间:

@Service
@RequiredArgsConstructor
public class CachedIdentifiersCache {

    private final LazyIdentifiersService slowServiceWithMultipleRestInvocations;
    private final CacheManager cacheManager;

    // 通过customerId查询,优先走缓存
    @Cacheable(value = "identifiers_cache_by_customer_id", key = "#customerId", sync = true)
    public Identifiers getCachedIdentifiers(Long customerId) {
        Identifiers identifiers = slowServiceWithMultipleRestInvocations.getIdentifiers();
        // 主动将结果存入accountNumber对应的缓存
        cacheManager.getCache("identifiers_cache_by_account_number")
                .put(identifiers.getAccountNumber(), identifiers);
        return identifiers;
    }

    // 通过accountNumber查询,优先走缓存
    @Cacheable(value = "identifiers_cache_by_account_number", key = "#accountNumber", sync = true)
    public Identifiers getCachedIdentifiers(String accountNumber) {
        Identifiers identifiers = slowServiceWithMultipleRestInvocations.getIdentifiers();
        // 主动将结果存入customerId对应的缓存
        cacheManager.getCache("identifiers_cache_by_customer_id")
                .put(identifiers.getCustomerId(), identifiers);
        return identifiers;
    }
}

关键细节:

  • sync = true:开启缓存同步,避免并发场景下多个线程重复调用慢服务(缓存击穿);
  • 调用慢服务获取结果后,通过cacheManager手动将数据写入另一个缓存空间,确保两个缓存同时更新。

方案二:使用@Caching组合注解

将核心数据获取逻辑抽离,利用@Caching组合@CachePut注解,自动将结果存入两个缓存:

@Service
@RequiredArgsConstructor
public class CachedIdentifiersCache {

    private final LazyIdentifiersService slowServiceWithMultipleRestInvocations;

    // 通过customerId查询,缓存命中直接返回,未命中则调用核心方法
    @Cacheable(value = "identifiers_cache_by_customer_id", key = "#customerId", sync = true)
    public Identifiers getCachedIdentifiers(Long customerId) {
        return fetchAndCache(customerId, null);
    }

    // 通过accountNumber查询,缓存命中直接返回,未命中则调用核心方法
    @Cacheable(value = "identifiers_cache_by_account_number", key = "#accountNumber", sync = true)
    public Identifiers getCachedIdentifiers(String accountNumber) {
        return fetchAndCache(null, accountNumber);
    }

    // 核心方法:获取数据并自动同步到两个缓存
    @Caching(put = {
            @CachePut(value = "identifiers_cache_by_customer_id", key = "#result.customerId"),
            @CachePut(value = "identifiers_cache_by_account_number", key = "#result.accountNumber")
    })
    private Identifiers fetchAndCache(Long customerId, String accountNumber) {
        // 实际业务中需根据传入参数调用对应慢服务接口,示例中简化为无参调用
        if (customerId != null) {
            return slowServiceWithMultipleRestInvocations.getIdentifiers();
        } else {
            return slowServiceWithMultipleRestInvocations.getIdentifiers();
        }
    }
}

关键细节:

  • @Caching(put = ...):组合两个@CachePut注解,方法返回结果后,自动以customerId和accountNumber为key,分别存入对应缓存;
  • #result:Spring SpEL表达式,代表方法的返回值,用于动态获取缓存key;
  • 抽离核心逻辑后,代码更易维护,避免重复代码。

需求匹配验证

以你期望的用例为例:

  1. 调用getCachedIdentifiers("a"),此时identifiers_cache_by_account_number缓存为空;
  2. 触发调用慢服务获取Identifiers实例(accountNumber="a",customerId=1L);
  3. 通过上述方案的任一实现,结果会同时存入identifiers_cache_by_account_number(key="a")和identifiers_cache_by_customer_id(key=1L);
  4. 后续调用getCachedIdentifiers(1L)时,直接从identifiers_cache_by_customer_id缓存中读取结果,无需再调用慢服务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:52:09