Cache
系统Redis客户端为 redisson ,提供了基础的Redis操作,2.0.2 版本新增基于caffeine 的本地缓存。
配置
lihua-admin 下 application-dev.yml(开发) 配置文件可对Redisson进行配置
spring:
redis:
redisson:
config: |
singleServerConfig:
address: "redis://127.0.0.1:6379"
database: 0
# 命令超时时间
timeout: 3000
# 连接超时时间
connectTimeout: 10000
# 连接池最大连接数
connectionPoolSize: 64
# 最小空闲连接数
connectionMinimumIdleSize: 10
# 自定义序列化器
codec: !<com.lihua.cache.config.TypedRedissonJsonCodec> {}其中 codec 指向了 TypedRedissonJsonCodec 自定义序列化器,TypedRedissonJsonCodec 在IDEA中显示灰色(没有被调用)但不可删除!
Redis缓存
setCacheObject
redisCache.setCacheObject("user:1", user);- 参数:key - 缓存key,value - 缓存对象
- 返回值:无
- 说明:缓存单个对象数据到Redis(无过期时间)
setCacheObject
redisCache.setCacheObject("user:1", user, Duration.ofMinutes(30));- 参数:key - 缓存key,value - 缓存对象,duration - 过期时间
- 返回值:无
- 说明:缓存单个对象数据并设置过期时间
setCacheList
redisCache.setCacheList("user:list", userList);- 参数:key - 缓存key,valueList - 集合数据
- 返回值:无
- 说明:缓存List集合数据,会先清空原有数据再写入
setCacheMap
redisCache.setCacheMap("user:map", userMap);- 参数:key - 缓存key,map - Map集合
- 返回值:无
- 说明:缓存整个Map数据,会覆盖原有数据
setCacheMapItem
redisCache.setCacheMapItem("user:map", "1", user);- 参数:key - 缓存key,mapKey - Map中的key,mapValue - Map中的值
- 返回值:无
- 说明:向Map缓存中添加或更新单条数据
getCacheMapItem
User user = redisCache.getCacheMapItem("user:map", "1", User.class);- 参数:key - 缓存key,mapKey - Map中的key,clazz - 返回对象类型
- 返回值:T 对象
- 说明:获取Map中指定key的数据并转换为指定类型
removeMapItem
redisCache.removeMapItem("user:map", "1");- 参数:key - 缓存key,mapKey - Map中的key
- 返回值:无
- 说明:删除Map中指定key的数据
getCacheObject
User user = redisCache.getCacheObject("user:1", User.class);- 参数:key - 缓存key,clazz - 返回对象类型
- 返回值:T 对象
- 说明:根据key获取缓存对象,并转换为指定类型
getCacheList
List<User> list = redisCache.getCacheList("user:list", User.class);- 参数:key - 缓存key,clazz - 集合元素类型
- 返回值:List<T> 集合
- 说明:获取List缓存并转换为指定类型集合
getCacheMap
Map<String, User> map = redisCache.getCacheMap("user:map", User.class);- 参数:key - 缓存key,clazz - Map value类型
- 返回值:Map<String, T>
- 说明:获取Map缓存并转换为指定类型
keys
Set<String> keys = redisCache.keys("user:");- 参数:prefix - key前缀
- 返回值:Set<String> key集合
- 说明:根据前缀匹配获取Redis中的key集合
keys - 全部
Set<String> keys = redisCache.keys();- 参数:无
- 返回值:Set<String> key集合
- 说明:获取Redis中所有key
scanKeys
Set<String> keys = redisCache.scanKeys("user:*");- 参数:pattern - 匹配规则
- 返回值:Set<String> key集合
- 说明:按指定规则扫描匹配Redis中的key
getExpireMinutes
Long minutes = redisCache.getExpireMinutes("user:1");- 参数:key - 缓存key
- 返回值:Long 剩余过期时间(分钟)
- 说明:获取key剩余过期时间,-1表示永不过期,-2表示不存在
setExpire
redisCache.setExpire("user:1", Duration.ofMinutes(10));- 参数:key - 缓存key,duration - 过期时间
- 返回值:无
- 说明:为指定key设置过期时间
delete
redisCache.delete("user:1");- 参数:key - 缓存key
- 返回值:Boolean 是否删除成功
- 说明:删除指定key的缓存数据
delete - 多个key
redisCache.delete("user:1", "user:2");- 参数:keys - 缓存key数组
- 返回值:Long 删除数量
- 说明:批量删除多个key
delete - 集合
redisCache.delete(keyList);- 参数:keys - 缓存key集合
- 返回值:Long 删除数量
- 说明:根据集合批量删除key
getRedisType
String type = redisCache.getRedisType("user:1");- 参数:key - 缓存key
- 返回值:String 数据类型
- 说明:获取key在Redis中的数据类型(string、list、hash等)
memoryInfo
String memory = redisCache.memoryInfo();- 参数:无
- 返回值:String 内存占用(MB)
- 说明:获取Redis当前内存使用情况(单位MB)
本地缓存 2.0.2
本地缓存定位为项目一级缓存,redis为二级缓存,查询缓存时使用 getWithFallback 方法。在 RedisKeyPrefixEnum 枚举中可配置本地缓存失效时间。主动失效调用 RedisPublisher 发布本地缓存失效消息。
setCache
LocalCacheManager.setCache(key, value);- 参数:key - 缓存key,value - 缓存对象
- 返回值:无
- 说明:缓存单个对象数据到caffeine(默认10s过期,TTL机制在
LocalCacheConfig配置)
getCache
LocalCacheManager.getCache(key, clazz);- 参数:key - 缓存key,clazz - 缓存对象class
- 返回值:缓存对象clazz对象数据
- 说明:根据key返回指定类型的对象数据
getWithFallback
LocalCacheManager.getWithFallback(key, clazz, BiFunction<String, Class<T>, T>);缓存对象
REDIS_CACHE_MANAGER 获取缓存参数、返回值与 getWithFallback 相同时,可简写为lambda表达式。
// 获取当前登录用户上下文信息,优先获取本地缓存,本地缓存不存在再从redis获取
LoginUser loginUser = LOCAL_CACHE_MANAGER.getWithFallback(decode, LoginUser.class, REDIS_CACHE_MANAGER::getCacheObject);缓存集合
对于List等缓存,需要调用getWithFallback的重载方法,参数二传入
new TypeReference<>(){},fallback 参数需要自行传入。
// 获取字典数据,优先获取本地缓存,本地缓存不存在再从redis获取
List<DictDataModel> dictCache = LOCAL_CACHE_MANAGER.getWithFallback(cacheKey, new TypeReference<>(){}, () -> REDIS_CACHE_MANAGER.getCacheList(cacheKey, DictDataModel.class));- 参数:key - 缓存key,clazz | TypeReference - 缓存对象类型 ,fallback - 本地缓存失效后调用Redis的方法,在
getWithFallback中延迟调用,并为本地缓存赋值 - 返回值:缓存对象clazz对象数据
- 说明:优先获取本地缓存数据,本地缓存不存在,通过 fallback 获取数据,获取到后再回填到本地缓存。fallback 一般为RedisCacheManager 获取数据方式,返回类型需与范型相同。
remove
LocalCacheManager.remove(key);- 参数:key - 缓存key
- 返回值:无
- 说明:删除本地缓存。一般由 LocalCacheInvalidateSubscriber 收到广播消息后调用
使本地缓存失效
为保证多实例部署下,所有实例缓存可同时主动失效,使用redis 的发布订阅模式进行通知。可使用 RedisPublisher 中 send 方法发送topic为INVALIDATE_LOCAL_CACHE(RedisTopicEnum 下维护)的消息,msg 为对应redis 的 key,发送后所有实例的LocalCacheInvalidateSubscriber 均会收到消息,执行删除本地缓存。
// 发送缓存失效广播
REDIS_PUBLISHER.send(RedisTopicEnum.INVALIDATE_LOCAL_CACHE.getValue(), cacheKey);统一前缀 2.0.2
RedisKeyPrefixEnum 枚举中定义的Redis的统一前缀,在此维护的Key可自动被 系统监控 缓存监控 识别。
localTTL 为本地缓存失效时间,当某个RedisKey启用了一级本地缓存,可在此处配置一级缓存过期时间。(null 为 10s)
/**
* Redis-Key前缀枚举
* 在此枚举中维护的前缀可通过「系统监控」-「缓存监控」进行具体类型的维护
* 不在此枚举中维护的前缀会在「系统监控」-「缓存监控」的OTHER类型中维护
*/
@Getter
@AllArgsConstructor
public enum RedisKeyPrefixEnum {
LOGIN_USER_REDIS_PREFIX("REDIS_CACHE_LOGIN_USER:", "登录用户", 10L),
DICT_DATA_REDIS_PREFIX("REDIS_CACHE_DICT_DATA:", "系统字典", null),
SYSTEM_SETTING_REDIS_PREFIX("REDIS_CACHE_SYSTEM_SETTING:", "系统设置", null),
SYSTEM_IP_BLACKLIST_REDIS_PREFIX("REDIS_CACHE_IP_BLACKLIST:", "IP黑名单", null),
PREVENT_DUPLICATE_SUBMIT_REDIS_PREFIX("REDIS_CACHE_REQUEST_SUBMIT:", "防重复提交", null),
CAPTCHA_TYPE_VALUE_REDIS_PREFIX("captcha:config:", "验证码缓存", null),
CAPTCHA_REDIS_PREFIX("REDIS_CACHE_CAPTCHA:", "验证码验证中", null),
SECONDARY_CAPTCHA_REDIS_PREFIX("REDIS_CACHE_SECONDARY_CAPTCHA:", "验证码二次验证", null),
CHUNK_UPLOAD_ID_REDIS_PREFIX("REDIS_CACHE_CHUNK_UPLOAD_ID:", "分片上传uploadId", null),
CHECK_PASSWORD_REDIS_PREFIX("REDIS_CACHE_CHECK_PASSWORD:", "检测密码", null),
ONCE_TOKEN_REDIS_PREFIX("REDIS_CACHE_ONCE_TOKEN:", "一次性令牌", null),
// 业务需要,非真实 manager key
OTHER("OTHER", "其他", null);
/**
* 缓存前缀
*/
private final String value;
/**
* 缓存标签,供页面显示缓存信息
*/
private final String label;
/**
* 本地缓存时长(秒)
* null 为不设置本地缓存
* 不设置本地缓存的key应用了二级缓存,默认10s ttl
*/
private final Long localTTL;
/**
* 获取全部枚举
*/
public static List<RedisKeyPrefixEnum> getRedisKeyPrefix() {
return new ArrayList<>(Arrays.asList(values()));
}
}广播主题 2.0.2
Redis pub/sub 模式下 topic 维护。
/**
* redis 发布订阅模式topic
*/
@Getter
@AllArgsConstructor
public enum RedisTopicEnum {
/**
* 清除本地缓存
*/
INVALIDATE_LOCAL_CACHE("invalidate_local_cache");
private final String value;
}
