发布于2026-04-20 阅读(0)
扫一扫,手机访问

本文详解如何在 Spring Cache 中通过一次业务方法调用,将同一份结果(如客户标识对象)同时写入多个命名缓存(如按 customerID 和 accountNumber 分别缓存),避免重复远程调用,提升多维度查询场景下的缓存命中率。
本文详解如何在 Spring Cache 中通过一次业务方法调用,将同一份结果(如客户标识对象)同时写入多个命名缓存(如按 customerID 和 accountNumber 分别缓存),避免重复远程调用,提升多维度查询场景下的缓存命中率。
在基于 Spring 的微服务中,常遇到「一个实体可通过多种唯一键查询」的场景:例如客户信息既可通过 customerId(Long 类型)获取,也可通过 accountNumber(String 类型)获取。理想情况下,首次任一维度查询触发远程调用后,应自动将结果同步写入两个缓存,使后续任意维度查询均可直接命中——但 Spring 原生 @Cacheable 仅支持单缓存写入,无法原生满足该需求。本文提供生产就绪的解决方案。
最简洁、可控且无需引入额外依赖的方式是:
@Service
@RequiredArgsConstructor
public class CachedIdentifiersService {
private final LazyIdentifiersService slowService;
private final CacheManager cacheManager;
// 获取缓存实例(推荐在构造时初始化,避免每次调用 getCache())
private final Cache cacheById = cacheManager.getCache("identifiers_cache_by_customer_id");
private final Cache cacheByAccount = cacheManager.getCache("identifiers_cache_by_account_number");
@Cacheable(value = "identifiers_cache_by_customer_id", key = "#customerId")
public Identifiers getIdentifiers(Long customerId) {
Identifiers identifiers = slowService.getIdentifiers();
// ✅ 主动写入 accountNumber 缓存
if (identifiers != null && identifiers.getAccountNumber() != null) {
cacheByAccount.put(identifiers.getAccountNumber(), identifiers);
}
return identifiers;
}
@Cacheable(value = "identifiers_cache_by_account_number", key = "#accountNumber")
public Identifiers getIdentifiers(String accountNumber) {
Identifiers identifiers = slowService.getIdentifiers();
// ✅ 主动写入 customerId 缓存
if (identifiers != null && identifiers.getCustomerId() != null) {
cacheById.put(identifiers.getCustomerId(), identifiers);
}
return identifiers;
}
}? 注意:cacheManager.getCache("xxx") 返回 Cache 实例为线程安全对象,可安全复用。
public void evictCustomer(Long customerId, String accountNumber) {
cacheById.evict(customerId);
cacheByAccount.evict(accountNumber);
}| 方案 | 说明 | 局限性 |
|---|---|---|
| @CachePut 组合 | 尝试用 @Cacheable 读 + @CachePut 写另一缓存 | Spring AOP 代理限制:同一 Bean 内部方法调用不触发 @CachePut,必须拆分为不同 Bean |
| 自定义 CacheResolver | 动态决定写入哪些缓存 | 无法区分「读操作」和「写操作」,易导致缓存污染 |
| AOP 切面拦截 | 在 @Cacheable 方法返回后统一写多缓存 | 侵入性强、调试复杂,且难以精准捕获 key 和 result |
单次调用写入多缓存的本质,是在 Spring Cache 的声明式语义之上,补充命令式缓存操作。本文提供的 CacheManager 显式写入方案平衡了简洁性、可读性与可控性,适用于绝大多数中高并发业务场景。只要遵循「主缓存由 @Cacheable 管理,副缓存由代码显式维护」的原则,并做好键唯一性与失效一致性保障,即可高效支撑多维度快速检索需求。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8