一、注解核心作用
@Cacheable
是Spring框架提供的声明式缓存注解,通过AOP机制实现以下功能:
-
将方法返回值自动缓存
-
相同参数调用时直接返回缓存结果
-
避免重复计算或数据库查询
二、注解参数详解
@Cacheable( value = CacheKeyConstants.CACHE_LOGISTICS_COMPANY_INFO_BY_CODE, key = "#p0" )
1. 核心参数说明
参数 | 作用 | 示例值 |
---|---|---|
value | 定义缓存组名称 | "logistics:company:info" |
cacheNames | 与value等价 | |
key | 指定缓存键生成规则(SpEL表达式) | #code 、#p0 、#root.methodName |
2. 键生成策略对比
// 简单参数 @Cacheable(key = "#code") // 复合键 @Cacheable(key = "#code + ':' + #type") // 对象属性 @Cacheable(key = "#company.id + ':' + #company.branch")
三、典型应用场景
物流公司信息查询案例
@Cacheable(value = "logistics:company:info", key = "#code") public LogisticsCompany getCompanyByCode(String code) { log.info("查询数据库:{}", code); return logisticsMapper.selectByCode(code); }
执行流程:
-
首次调用
getCompanyByCode("SF")
:-
执行方法体查询数据库
-
将结果缓存到Redis(键格式:
logistics:company:info:SF
)
-
-
后续相同参数调用:
-
直接返回缓存结果
-
方法体不再执行
-
四、缓存一致性保障
配套注解使用策略
注解 | 适用场景 | 示例 |
---|---|---|
@CacheEvict | 数据修改时清除缓存 | 更新/删除操作后触发 |
@CachePut | 强制更新缓存 | 始终执行方法体并刷新缓存 |
// 数据更新时清除缓存 @CacheEvict(value = "logistics:company:info", key = "#code") public void updateCompany(String code, CompanyDTO dto) { logisticsMapper.updateByCode(code, dto); }
五、Redis配置示例
application.yml
最佳实践配置:
spring: redis: host: 127.0.0.1 port: 6379 password: 123456 # 生产环境建议使用Vault管理 database: 0 # 建议不同环境使用不同DB cache: type: redis redis: time-to-live: 3600s # 建议设置合理TTL key-prefix: "cache:" # 推荐使用业务前缀 use-key-prefix: true # 避免键冲突 cache-null-values: false # 防止缓存穿透
六、常见问题解决方案
-
缓存雪崩:
redis: time-to-live: ${CACHE_TTL:3600} + random(300) # 添加随机过期时间
-
缓存穿透:
@Cacheable(unless = "#result == null") // 不缓存null结果
-
本地二级缓存(Caffeine + Redis):
cache: multi: caffeine: spec: maximumSize=500,expireAfterWrite=60s redis: defaultTimeToLive: 30m
七、性能对比测试
压测指标(JMeter 1000并发):
模式 | QPS | 平均响应时间 |
---|---|---|
无缓存 | 128 | 780ms |
@Cacheable | 4200 | 23ms |
测试环境:Redis 6.2 / Spring Boot 2.7 / 阿里云4C8G
最佳实践建议:
-
高频查询+低频修改的场景最适合缓存
-
分布式环境建议配合
@CacheConfig
统一配置 -
重要业务建议添加缓存命中率监控