问题说明
在高性能的服务架构设计中,缓存是一个不可或缺的环节。在实际的项目中,我们通常会将一些热点数据存储到Redis或MemCache这类缓存中间件中,只有当缓存的访问没有命中时再查询数据库。在提升访问速度的同时,也能降低数据库的压力。
随着不断的发展,这一架构也产生了改进,在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与服务性能。于是,就产生了使用本地缓存作为一级缓存,再加上远程缓存作为二级缓存的两级缓存架构。

准备
集成Redission:SpringBoot 整合Redisson重写cacheName支持多参数
com.github.ben-manes.caffeinecaffeine
配置文件
增加本地缓存是为了解决高并发下频繁查询Redis的问题,配置了expireAfterWrite最后一次写入或访问后经过固定时间过期为30秒,例如一次访问一个页面一直刷新,在30秒内无论怎么刷新都会走本地缓存,而且就算在29秒重新获取了缓存,也会重新计算30秒
@EnableCaching开启缓存功能,也可以加在启动类上
package com.example.redisson.config;
import com.example.redisson.manager.PlusSpringCacheManager;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* 缓存配置
*
* @author Lion Li
*/
@Configuration
@EnableCaching
public class CacheConfig {
/**
* caffeine 本地缓存处理器
*/
@Bean
public Cache
装饰器
- put方法是cache使用的也就是Redission ,会自动加上cacheNames
- 而caffeine不使用cacheNames ,get方法的key是哪个就会缓存哪个key
- 所以为了解决key相同,cacheNames 不同的问题增加了getUniqueKey方法
getName( ) = cacheNames
一个CacheNams对应一个Cache对象
package org.dromara.common.redis.manager;
import cn.hutool.core.lang.Console;
import org.dromara.common.core.utils.SpringUtils;
import org.springframework.cache.Cache;
import java.util.concurrent.Callable;
/**
* Cache 装饰器模式(用于扩展 Caffeine 一级缓存)
*
* @author LionLi
*/
public class CaffeineCacheDecorator implements Cache {
private static final com.github.benmanes.caffeine.cache.Cache
修改自定义PlusSpringCacheManager,注入装饰器

使用
@Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null")
@GetMapping("/test1")
public R test1(String key, String value) {
System.out.println("test1-->调用方法体");
return R.ok("操作成功", value);
}
因为@Cacheable注解上来就会调用get方法,所以可以触发本地缓存,@CachePut注解则不行

查看源码可知,如果一级没有获取到,则获取二级

缓存工具类
package com.example.redisson.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.redisson.api.RMap;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import java.util.Set;
/**
* 缓存操作工具类 {@link }
*
* @author Michelle.Chung
* @date 2022/8/13
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings(value = {"unchecked"})
public class CacheUtils {
private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class);
/**
* 获取缓存组内所有的KEY
*
* @param cacheNames 缓存组名称
*/
public static Set
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持IT俱乐部。
