基于Spring Boot的多级缓存系统设计

在构建大规模应用时,缓存系统是提高性能的关键因素之一。为了更有效地利用缓存,我们可以设计一个基于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的多级缓存系统。这个设计支持在本地内存和分布式缓存之间实现多级缓存,从而更好地满足不同场景下的性能需求。在实际应用中,可以根据具体需求调整缓存的层次和配置,以达到最佳性能和资源利用率。

相关推荐
Jacob023413 分钟前
Node.js 性能瓶颈与 Rust + WebAssembly 实战探索
后端·rust·node.js
Monika Zhang22 分钟前
Redis缓存详解及常见问题解决方案
数据库·redis·缓存
王中阳Go22 分钟前
分库分表之后如何使用?面试可以参考这些话术
后端·面试
知其然亦知其所以然27 分钟前
ChatGPT太贵?教你用Spring AI在本地白嫖聊天模型!
后端·spring·ai编程
kinlon.liu1 小时前
内网穿透 FRP 配置指南
后端·frp·内网穿透
Monika Zhang1 小时前
Memcached 缓存详解及常见问题解决方案
数据库·缓存·memcached
kfyty7251 小时前
loveqq-mvc 再进化,又一款分布式网关框架可用
java·后端
Dcr_stephen1 小时前
Spring 事务中的 beforeCommit 是业务救星还是地雷?
后端
raoxiaoya1 小时前
Golang中的`io.Copy()`使用场景
开发语言·后端·golang
二闹2 小时前
高效开发秘籍:CRUD增强实战
后端·设计模式·性能优化