在构建大规模应用时,缓存系统是提高性能的关键因素之一。为了更有效地利用缓存,我们可以设计一个基于Spring Boot的多级缓存系统,结合本地内存缓存(如Caffeine)和分布式缓存(如Redis)。以下是一个简单的多级缓存系统的设计概要:
1. 选择缓存框架
在Spring Boot中,我们可以选择合适的缓存框架,比如Ehcache、Redis、Caffeine等。可以通过在pom.xml中引入相应的依赖来集成这些框架。
2. 配置缓存
在application.properties或application.yml中配置缓存的相关属性,如缓存类型、大小、过期时间等。
3. 定义缓存管理类
创建一个缓存管理类,用于配置多级缓存,指定各级缓存的顺序和策略。
java
package com.nbsaas.boot.config;
import com.github.benmanes.caffeine.cache.CaffeineSpec;
import com.nbsaas.boot.cache.MultiLevelCacheManager;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfig {
@Primary
@Order(Ordered.HIGHEST_PRECEDENCE)
@Bean
public CacheManager cacheManager(CaffeineCacheManager caffeineCacheManager,RedisCacheManager redisCacheManager) {
MultiLevelCacheManager multiLevelCacheManager = new MultiLevelCacheManager();
multiLevelCacheManager.addCache(caffeineCacheManager);
multiLevelCacheManager.addCache(redisCacheManager);
return multiLevelCacheManager;
}
@Bean
public CaffeineCacheManager caffeineCacheManager() {
// 配置Caffeine缓存
CaffeineCacheManager cacheManager = new CaffeineCacheManager("caffeineCache","yourCacheName");
cacheManager.setCaffeineSpec(caffeineSpec());
return cacheManager;
}
@Order(Ordered.LOWEST_PRECEDENCE)
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
private CaffeineSpec caffeineSpec() {
// 配置Caffeine缓存规格
return CaffeineSpec.parse("maximumSize=100");
}
}
4. 实现缓存管理器和缓存
实现MultiLevelCacheManager类和MultiLevelCache类,用于管理和协调多个缓存层次。
java
package com.nbsaas.boot.cache;
import org.springframework.cache.Cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;
public class MultiLevelCache implements Cache {
private final ArrayList<Cache> caches = new ArrayList<>();
public void addCache(Cache cache) {
caches.add(cache);
}
@Override
public String getName() {
return "multiLevelCache";
}
@Override
public Object getNativeCache() {
return this;
}
@Override
public ValueWrapper get(Object key) {
for (Cache cache : caches) {
ValueWrapper wrapper = cache.get(key);
if (wrapper != null) {
return wrapper;
}
}
return null;
}
@Override
public <T> T get(Object key, Class<T> type) {
ValueWrapper wrapper = get(key);
return (wrapper != null) ? (T) wrapper.get() : null;
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
ValueWrapper wrapper = get(key);
T obj= (wrapper != null) ? (T) wrapper.get() : null;
return obj;
}
@Override
public void put(Object key, Object value) {
for (Cache cache : caches) {
cache.put(key, value);
}
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
ValueWrapper wrapper = get(key);
if (wrapper == null) {
put(key, value);
return null;
}
return wrapper;
}
@Override
public void evict(Object key) {
for (Cache cache : caches) {
cache.evict(key);
}
}
@Override
public boolean evictIfPresent(Object key) {
return Cache.super.evictIfPresent(key);
}
@Override
public void clear() {
for (Cache cache : caches) {
cache.clear();
}
}
@Override
public boolean invalidate() {
boolean result=true;
for (Cache cache : caches) {
result= cache.invalidate();
}
return result;
}
}
java
package com.nbsaas.boot.cache;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import java.util.ArrayList;
import java.util.Collection;
public class MultiLevelCacheManager implements CacheManager {
private final ArrayList<CacheManager> cacheManagers = new ArrayList<>();
public static final int REDIS_CACHE_EXPIRATION = 600; // Redis缓存过期时间(秒)
public void addCache(CacheManager cacheManager) {
cacheManagers.add(cacheManager);
}
@Override
public Cache getCache(String name) {
MultiLevelCache multiLevelCache = new MultiLevelCache();
for (CacheManager cacheManager : cacheManagers) {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
multiLevelCache.addCache(cache);
}
}
return multiLevelCache;
}
@Override
public Collection<String> getCacheNames() {
Collection<String> cacheNames = new ArrayList<>();
for (CacheManager cacheManager : cacheManagers) {
cacheNames.addAll(cacheManager.getCacheNames());
}
return cacheNames;
}
}
5. 使用缓存
在Service层或方法上使用@Cacheable、@CachePut、@CacheEvict等注解来标记需要缓存的方法。
java
@Service
public class MyService {
@Cacheable(value = "caffeineCache", key = "#id")
public String getCachedData(String id) {
// 查询数据库或其他业务逻辑
return "Cached Data for " + id;
}
}
通过以上步骤,我们成功建立了一个基于Spring Boot的多级缓存系统。这个设计支持在本地内存和分布式缓存之间实现多级缓存,从而更好地满足不同场景下的性能需求。在实际应用中,可以根据具体需求调整缓存的层次和配置,以达到最佳性能和资源利用率。