Springboot集成一二级缓存(caffeine+redis)
1119 字
6 分钟
Springboot集成一二级缓存(caffeine+redis)

目的:主要是实现查询效率上的优化,减少数据库方面的压力,提升系统的性能
L1:一级缓存,主要是本地内存缓存,不需要网络传输,实时性很高,适合存储数据量少的数据,不可以持久化存储。
L2:二级缓存,独立于服务器/程序之外的外部缓存,适合存储数据量大大一点的数据,可持久化存储,性能稍慢于一级缓存,如redis,支持集群部署,多节点共享数据。
1.maven依赖
对于2.7.x及以上版本的无需指定caffeine版本号,spring会自动去引入兼容版本。
<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>2.开始配置
2.1 添加@EnableCaching注解
在启动类上添加@EnableCaching开关。
@EnableCaching@SpringBootApplicationpublic class SystemApplication { .......}2.2 创建CacheConfig类,注入到spring管理中
一个是Caffeine本地缓存管理器,一个是多级缓存管理器。
@Configuration@EnableCachingpublic class CacheConfig {
@Bean public CacheManager caffeineCacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); cacheManager.setCaffeine(Caffeine.newBuilder() // 初始化容量 .initialCapacity(100) // 最大容量 .maximumSize(1000) // 过期时间 .expireAfterWrite(3600, TimeUnit.SECONDS) .recordStats()); return cacheManager; }
* 一二级缓存管理器 * * @param caffeineCacheManager Caffeine缓存管理 * @param redisCacheUtil redis工具类 * @return */ @Primary @Bean public CacheManager levelCacheManager(@Qualifier(value = "caffeineCacheManager") CacheManager caffeineCacheManager, @Autowired RedisCacheUtil redisCacheUtil) { return new LevelCacheManager(caffeineCacheManager, redisCacheUtil); }
}2.3 创建一二级缓存管理器
里面同时实现了对每个key值自定义过期时间,默认是设置通用过期时长。
public class LevelCacheManager implements CacheManager {
private final CaffeineCacheManager caffeineCacheManager; private final RedisCacheUtil redisCacheUtil;
public LevelCacheManager(CacheManager caffeineCacheManager, RedisCacheUtil redisCacheUtil) { this.caffeineCacheManager = (CaffeineCacheManager) caffeineCacheManager; this.redisCacheUtil = redisCacheUtil; }
@Override public Cache getCache(String name) { CaffeineCache caffeineCache = parseName(name); return new LevelCache(name, caffeineCache, redisCacheUtil); }
@Override public Collection<String> getCacheNames() { return Collections.emptyList(); }
private CaffeineCache parseName(String name) { long duration = 0; // 默认60分钟 if (name.contains("#")) { // 解析名称中的有效期信息 String[] parts = name.split("#"); name = parts[0]; if (parts.length > 1) { try { duration = Long.parseLong(parts[1]); } catch (NumberFormatException e) { e.printStackTrace(); } } } com.github.benmanes.caffeine.cache.Cache<Object, Object> build = Caffeine.newBuilder() // 初始化容量 .initialCapacity(100) // 最大容量 .maximumSize(1000) // 过期时间 .expireAfterWrite(duration, TimeUnit.SECONDS).recordStats().build(); CaffeineCache caffeineCache = (CaffeineCache) caffeineCacheManager.getCache(name); CaffeineCache caffeineCache2 = new CaffeineCache(name, build); if (duration > 0) { redisCacheUtil.setEXPIRE_TIME(duration); return caffeineCache2; } redisCacheUtil.setEXPIRE_TIME(3600L); return caffeineCache; }2.4 自定义一,二级缓存操作类
实现一二级缓存顺序读取,先查一级再查二级缓存,序列化方式保持一致。
public class LevelCache implements Cache {
private final RedisCacheUtil redisCacheUtil; private final String name; private final CaffeineCache caffeineCache;
public LevelCache(String name, CaffeineCache caffeineCache, RedisCacheUtil redisCacheUtil){ this.name=name; this.caffeineCache = caffeineCache; this.redisCacheUtil = redisCacheUtil; }
@Override public String getName() { return name; }
/** * 仅当缓存中不存在指定键时,才将键值对存入缓存。若键已存在,不会进行覆盖操作,而是返回缓存中现有的值。 * @param key * @param value * @return */ @Override public ValueWrapper putIfAbsent(Object key, Object value) { ValueWrapper existingValue = this.get(key); if (existingValue == null) { caffeineCache.put(key, value); } Object obj = redisCacheUtil.get(String.valueOf(key)); if (obj==null){ redisCacheUtil.set(String.valueOf(key),value,redisCacheUtil.getEXPIRE_TIME()); } return this.get(key); }
@Override public Object getNativeCache() { return null; }
/** * 获取缓存中的数据 * @param key * @return */ @Override public ValueWrapper get(Object key) { ValueWrapper valueWrapper = caffeineCache.get(key); if (valueWrapper != null){ return valueWrapper; } Object value= redisCacheUtil.get(String.valueOf(key)); if(value!=null){ caffeineCache.put(key, value); return this.get(key); } return null; }
/** * 获取缓存中数据,具体对象 * @param key * @param type * @return * @param <T> */ @Override public <T> T get(Object key, Class<T> type) { T value = caffeineCache.get(key, type); if (value != null){ return value; } Object rValue = redisCacheUtil.get(String.valueOf(key)); if (rValue != null){ caffeineCache.put(key,rValue); return (T) rValue; } return null; }
/** * 如果一二级缓存中都不存在情况下,使用自定义的valueLoader加载数据,并缓存到一级缓存和二级缓存中 * @param key * @param valueLoader * @return * @param <T> */ @Override public <T> T get(Object key, Callable<T> valueLoader) { ValueWrapper value=this.get(key); if (value!=null) { return (T) value.get(); }else{ Object obj; try { obj = valueLoader.call(); } catch (Exception e) { throw new RuntimeException(e); } caffeineCache.put(key,obj); redisCacheUtil.set(String.valueOf(key),obj,redisCacheUtil.getEXPIRE_TIME()); return (T)obj; } }
/** * 填入一二级缓存 * @param key * @param value */ @Override public void put(Object key, Object value) { caffeineCache.put(key,value); redisCacheUtil.set(String.valueOf(key),value,redisCacheUtil.getEXPIRE_TIME()); }
/** * 移除指定key值的一二级缓存 * @param key */ @Override public void evict(Object key) { caffeineCache.evict(key); redisCacheUtil.del(String.valueOf(key)); }
/** * 删除所有一二级缓存 */ @Override public void clear() { caffeineCache.clear(); redisCacheUtil.delByPrefix(CacheKeyGenerator.KEY_PREFIX); }}2.5 自定义key值前缀工具类
在配合方法参数时,可以自己拼接前缀在key前面,实现统一管理。
public class CacheKeyGenerator {
public static final String KEY_PREFIX = "levelCache:"; public static final String USER_CACHE = "userCaches";
public static String generateKey(String name) { return KEY_PREFIX + name; }}2.6 使用注解方式实现案例
@Override @Cacheable(cacheNames = CacheKeyGenerator.USER_CACHE+"#10", key= "T(com.makingTeam.config.cache.CacheKeyGenerator).generateKey(#name)") public Object login(String name, String pwd) { Map<Object, Object> objectObjectMap = new HashMap<>(); objectObjectMap.put(name, pwd); log.info("login-----查找数据库"); return objectObjectMap; }
@Override @CachePut(cacheNames = CacheKeyGenerator.USER_CACHE+"#30", key= "T(com.makingTeam.config.cache.CacheKeyGenerator).generateKey(#name)") public Object updateLogin(String name, String pwd) { Map<Object, Object> objectObjectMap = new HashMap<>(); objectObjectMap.put(name, pwd); log.info("updateLogin----查找数据库"); return objectObjectMap; }
@CacheEvict(cacheNames = CacheKeyGenerator.USER_CACHE, key= "T(com.makingTeam.config.cache.CacheKeyGenerator).generateKey(#name)") @Override public void del(String name) { log.info("del----删除"); }完结!
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
Springboot集成一二级缓存(caffeine+redis)
https://blog.xzhiyee.com/posts/cache/相关文章智能推荐
1
Docker容器内mysql忘记密码如何重置?
技术笔记2026-09-17
2
Docker基本命令
技术笔记2026-09-17
3
Elasticsearch安装(linux)
技术笔记2026-09-17
4
(auto-fit,auto-fill)两行代码就能适应任何屏幕?
技术笔记2026-09-16
5
java位运算
技术笔记2026-09-16
随机文章随机推荐












