缓存失效、清理与高级用法
2025/9/17大约 3 分钟
Spring Cache 缓存失效、过期、清理与高级用法
前置知识
建议你已掌握 Spring Cache 基础与常用实现配置。
目录
缓存失效策略与原理
- 定时过期:缓存数据在设定时间后自动失效(如 expireAfterWrite、expireAfterAccess)
- 主动清理:通过 @CacheEvict 注解或 CacheManager 手动清理
- 容量淘汰:超出最大容量后自动淘汰(如 Caffeine maximumSize)
过期与清理机制
- Caffeine/Redis 等实现支持多种过期策略
- 可通过 yml 配置过期时间、最大容量等
- Redis 支持持久化,Caffeine 为本地内存
Caffeine 过期配置示例
spring:
cache:
caffeine:
spec: maximumSize=1000,expireAfterWrite=10m,expireAfterAccess=5m
Redis 过期配置示例
spring:
cache:
redis:
time-to-live: 600000 # 10分钟,单位毫秒
@CacheEvict 高级用法
@CacheEvict
支持按 key、按 cacheName、全部清理、条件清理等- 常用于数据更新、删除、批量清理等场景
批量与全部清理示例
// 删除单个缓存
@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) { ... }
// 批量清理
@CacheEvict(value = "user", allEntries = true)
public void clearUserCache() { ... }
// 条件清理
@CacheEvict(value = "user", key = "#id", condition = "#id > 100")
public void evictIfLargeId(Long id) { ... }
条件缓存与同步刷新
@Cacheable
支持 condition、unless 表达式,灵活控制缓存sync = true
支持同步刷新,防止缓存击穿(Caffeine 支持)
条件缓存与同步刷新示例
// 仅缓存 id > 100 的结果
@Cacheable(value = "user", key = "#id", condition = "#id > 100")
public User getUser(Long id) { ... }
// 方法返回 null 不缓存
@Cacheable(value = "user", key = "#id", unless = "#result == null")
public User getUserOrNull(Long id) { ... }
// 同步刷新(防止击穿)
@Cacheable(value = "user", key = "#id", sync = true)
public User getUserSync(Long id) { ... }
缓存穿透与雪崩防护
- 缓存穿透:查询不存在的数据,缓存未命中导致频繁访问数据库
- 解决:对空结果也缓存,或用布隆过滤器
- 缓存雪崩:大量缓存同一时间失效,导致后端压力骤增
- 解决:过期时间加随机、分批失效、限流
防护代码片段
// 防止穿透:空对象也缓存
@Cacheable(value = "user", key = "#id", unless = "#result == null")
public User getUser(Long id) { ... }
// 雪崩防护:过期时间加随机(Redis配置)
spring:
cache:
redis:
time-to-live: 600000 # 10分钟
key-prefix: user:
# 可在业务中为不同key设置不同ttl
实战代码示例
CacheEvictDemo.java
@Service
public class CacheEvictDemo {
// 删除单个缓存
@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) { /* ... */ }
// 批量清理
@CacheEvict(value = "user", allEntries = true)
public void clearUserCache() { /* ... */ }
// 条件清理
@CacheEvict(value = "user", key = "#id", condition = "#id > 100")
public void evictIfLargeId(Long id) { /* ... */ }
}
常见问题与小结
常见问题
- 缓存未及时失效:检查 @CacheEvict 是否正确、allEntries 用法
- 缓存击穿/雪崩:合理设置过期时间、同步刷新、限流
- 空对象未缓存:unless/condition 表达式控制
- 批量清理无效:确认 allEntries=true,cacheName 正确
- 合理配置过期、清理策略,防止缓存穿透与雪崩
- 推荐结合 condition、unless、sync 等高级用法
- 后续将介绍 Spring Cache 实战技巧、性能优化与常见问题
本文为 Spring Cache 系列教程第三篇,下一篇将介绍实战技巧、性能优化与常见问题,敬请期待!