基于Spring Boot的多级缓存架构实现
基于Spring Boot的多级缓存架构实现
以下是一个基于Spring Boot的多级缓存架构实现示例
多级缓存架构实现方案
1. 依赖配置(pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 缓存配置类
@Configuration
@EnableCaching
public class MultiLevelCacheConfig {
// 一级缓存(本地缓存)
@Bean
public CacheManager caffeineCacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager();
manager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(30, TimeUnit.SECONDS)); // 本地缓存比Redis缓存更短
return manager;
}
// 二级缓存(Redis缓存)
@Bean
public CacheManager redisCacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(5))
.serializeValuesWith(SerializationPair.fromSerializer(RedisSerializer.json()));
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.transactionAware()
.build();
}
// 组合缓存管理器
@Bean
@Primary
public CacheManager multiLevelCacheManager(
@Qualifier("caffeineCacheManager") CacheManager level1,
@Qualifier("redisCacheManager") CacheManager level2) {
return new MultiLevelCacheManager(level1, level2);
}
}
3. 多级缓存管理器实现
public class MultiLevelCacheManager implements CacheManager {
private final CacheManager level1; // 本地缓存
private final CacheManager level2; // Redis缓存
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>();
public MultiLevelCacheManager(CacheManager level1, CacheManager level2) {
this.level1 = level1;
this.level2 = level2;
}
@Override
public Cache getCache(String name) {
return cacheMap.computeIfAbsent(name,
key -> new MultiLevelCache(
level1.getCache(name),
level2.getCache(name)
));
}
@Override
public Collection<String> getCacheNames() {
return Stream.concat(
level1.getCacheNames().stream(),
level2.getCacheNames().stream()
).collect(Collectors.toSet());
}
// 多级缓存实现
static class MultiLevelCache implements Cache {
private final Cache level1;
private final Cache level2;
private final String name;
public MultiLevelCache(Cache level1, Cache level2) {
this.level1 = level1 != null ? level1 : new NoOpCache();
this.level2 = level2 != null ? level2 : new NoOpCache();
this.name = level1.getName() + ":" + level2.getName();
}
@Override
public String getName() {
return name;
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public ValueWrapper get(Object key) {
// 先查一级缓存
ValueWrapper value = level1.get(key);
if (value == null) {
// 二级缓存查询
value = level2.get(key);
if (value != null) {
// 回填一级缓存
level1.put(key, value.get());
}
}
return value;
}
@Override
public <T> T get(Object key, Class<T> type) {
// 实现逻辑类似get方法
T value = level1.get(key, type);
if (value == null) {
value = level2.get(key, type);
if (value != null) {
level1.put(key, value);
}
}
return value;
}
@Override
public void put(Object key, Object value) {
// 同时写入两级缓存
level1.put(key, value);
level2.put(key, value);
}
@Override
public void evict(Object key) {
// 同时清除两级缓存
level1.evict(key);
level2.evict(key);
}
@Override
public void clear() {
level1.clear();
level2.clear();
}
}
// 空缓存实现(容错)
static class NoOpCache implements Cache {
// 实现基础的Cache方法,返回空值
}
}
4. 业务层使用
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public Product getProduct(Long id) {
// 数据库查询逻辑
return productRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Product not found"));
}
@CacheEvict(value = "products", key = "#product.id")
public void updateProduct(Product product) {
productRepository.save(product);
}
}
5. 配置说明(application.yml)
spring:
cache:
multi-level:
level1:
ttl: 30s # 本地缓存时间
max-size: 1000
level2:
ttl: 5m # Redis缓存时间
redis:
host: redis-cluster.prod
port: 6379
timeout: 2000ms
关键实现要点
- 缓存层级策略
- 一致性保障
- 写操作:同时清除两级缓存(
@CacheEvict
) - 读操作:二级缓存命中后自动回填一级缓存
- TTL策略:一级缓存TTL(30s) < 二级缓存TTL(5m)
- 性能优化
- 本地缓存:使用Caffeine高性能缓存库
- 异步回填:可扩展为异步加载(需自定义CacheLoader)
- 批量操作:支持@Cacheable的批量查询优化
扩展建议
- 缓存预热
@PostConstruct
public void preloadHotData() {
// 加载热点数据到缓存
hotProducts.forEach(product ->
cacheManager.getCache("products").put(product.getId(), product));
}
- 监控集成
@Bean
public MeterRegistryCustomizer<MeterRegistry> cacheMetrics() {
return registry -> {
CaffeineCacheManager caffeine = context.getBean(CaffeineCacheManager.class);
RedisCacheManager redis = context.getBean(RedisCacheManager.class);
// 注册Caffeine监控
CacheMetrics.monitor(registry, caffeine, "level1");
// 注册Redis监控
CacheMetrics.monitor(registry, redis, "level2");
};
}
- 防雪崩策略
// 在MultiLevelCache.get方法中添加
ValueWrapper get(Object key) {
try {
// 添加分布式锁检查
if (lockManager.tryLock(key)) {
// 实际查询逻辑
}
} finally {
lockManager.unlock(key);
}
}