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;- 抽离核心逻辑后,代码更易维护,避免重复代码。
需求匹配验证
以你期望的用例为例:
- 调用
getCachedIdentifiers("a"),此时identifiers_cache_by_account_number缓存为空; - 触发调用慢服务获取
Identifiers实例(accountNumber="a",customerId=1L); - 通过上述方案的任一实现,结果会同时存入
identifiers_cache_by_account_number(key="a")和identifiers_cache_by_customer_id(key=1L); - 后续调用
getCachedIdentifiers(1L)时,直接从identifiers_cache_by_customer_id缓存中读取结果,无需再调用慢服务。
内容的提问来源于stack exchange,提问作者snej0keee
相关产品推荐
相关产品推荐

