Spring Boot缓存优化:@Cacheable高级应用与性能调优
- 发布时间:2025-03-16 02:49:38
- 本文热度:浏览 31 赞 0 评论 0
- 文章标签: Spring Boot Spring Cache 缓存优化
- 全文共1字,阅读约需1分钟
缓存基础配置与常规实践
1. 注解参数全解析
@Cacheable(value = "userProfile",
key = "#userId + '_' + #type",
condition = "#userId.startsWith('VIP')",
unless = "#result == null || #result.isDisabled()")
public UserProfile getUserProfile(String userId, String type) {
// 数据库查询逻辑
}
- value/cacheNames:定义逻辑缓存分区,支持多缓存声明
- key:SpEL表达式构建复合键,建议使用参数组合表达式
- condition:前置条件判断,满足条件才执行缓存
- unless:后置结果判断,否决缓存写入
2. 缓存管理器选型
spring:
cache:
type: redis
redis:
time-to-live: 30m
cache-null-values: true
key-prefix: APP_CACHE_
use-key-prefix: true
caffeine:
spec: maximumSize=500,expireAfterWrite=10m
多级缓存组合配置示例:
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration redisConfig = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CaffeineCacheManager localCacheManager = new CaffeineCacheManager();
localCacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(5, TimeUnit.MINUTES));
return new CompositeCacheManager(localCacheManager,
RedisCacheManager.builder(factory).cacheDefaults(redisConfig).build());
}
高级缓存策略实现
3. 防缓存穿透方案
@Cacheable(value = "productDetail",
unless = "#result == null")
public Product getProductDetail(Long productId) {
Product product = productDao.getById(productId);
if (product == null) {
// 记录异常访问日志
auditService.recordInvalidQuery(productId);
// 返回特殊空对象
return Product.EMPTY;
}
return product;
}
4. 缓存预热机制
@Scheduled(fixedRate = 30_000)
@CacheEvict(value = "hotProducts", allEntries = true)
public void preloadHotProducts() {
List<Product> products = productService.getTop100HotProducts();
products.parallelStream().forEach(p -> {
cacheManager.getCache("hotProducts")
.put(p.getId(), p);
});
}
性能优化实战技巧
5. 序列化优化配置
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(
new ObjectMapper().registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false),
Object.class
);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
return template;
}
6. 并发控制优化
@Cacheable(value = "inventory",
key = "#productId",
sync = true)
public Integer getProductInventory(Long productId) {
return inventoryService.getRealTimeInventory(productId);
}
监控与诊断方案
7. 缓存命中率监控
@Aspect
@Component
@Slf4j
public class CacheMonitorAspect {
@Autowired
private CacheMetricsCollector metricsCollector;
@Around("@annotation(org.springframework.cache.annotation.Cacheable)")
public Object monitorCache(ProceedingJoinPoint joinPoint) throws Throwable {
String cacheName = ((Cacheable) ((MethodSignature) joinPoint.getSignature())
.getMethod().getAnnotation(Cacheable.class)).value()[0];
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
metricsCollector.recordCacheAccess(cacheName, duration, result != null);
return result;
}
}
典型问题解决方案
8. 缓存数据版本控制
@Cacheable(value = "userConfig",
key = "#userId",
cacheResolver = "versionAwareCacheResolver")
public UserConfig getUserConfig(String userId) {
return configService.getLatestConfig(userId);
}
@Bean
public CacheResolver versionAwareCacheResolver() {
return new CacheResolver() {
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
String version = configService.getCurrentSchemaVersion();
String cacheName = context.getOperation().getCacheNames().iterator().next() + "_v" + version;
return Collections.singleton(cacheManager.getCache(cacheName));
}
};
}
9. 大Value分块缓存
@Cacheable(value = "largeReport",
key = "#reportId")
public Report getLargeReport(String reportId) {
Report report = reportService.generateReport(reportId);
// 分块存储附加数据
cacheManager.getCache("reportChunks")
.put(reportId + "_attachments",
splitAttachments(report.getAttachments()));
return report.withoutAttachments();
}
调试与问题排查
10. 缓存追踪日志
logging.level.org.springframework.cache=TRACE
logging.level.net.sf.ehcache=DEBUG
logging.level.com.github.benmanes.caffeine=DEBUG
诊断日志分析要点:
- Cache miss/hit 日志模式识别
- 序列化异常堆栈跟踪
- 缓存淘汰策略执行记录
- Redis连接池状态监控
正文到此结束
相关文章
热门推荐
评论插件初始化中...