spring使用RedisCacheManager管理key的一些问题
Posted 正在战斗中
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring使用RedisCacheManager管理key的一些问题相关的知识,希望对你有一定的参考价值。
spring可以很好地管理各种内存的快速缓存。
这些常见的内存缓存库实现方式有redis,Ehcache。
本文阐述的是redis,毕竟这个东西相当容易使用。
spring通过 org.springframework.cache.Cache 和org.springframework.cache.CacheManager两个接口来管理缓存
redis的cache实现类是 RedisCacheManager,它们的关系是这样的:
object
<-AbstractCacheManager=>(CacheManager, InitializingBean)
<-AbstractTransactionSupportingCacheManager
<-RedisCacheManager
可以看出RedisCacheManager实现了接口CacheManager接口。
一、如何自定义redis中key
如果使用默认的方式来注册RedisCacheManager,如下:
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(this.cacheTimeOutHour))
假定注解是这样的:
@Cacheable(value="getUserPoJoById",key="#userId")
那么生成redis的key是形如这样的:
getUserPoJoById::103
其中双冒号(::)是分隔符。
这是因为RedisCacheConfiguration.defaultCacheConfig()的源码如下:
public static RedisCacheConfiguration defaultCacheConfig() { return defaultCacheConfig(null); } public static RedisCacheConfiguration defaultCacheConfig(@Nullable ClassLoader classLoader) { DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(); registerDefaultConverters(conversionService); return new RedisCacheConfiguration(Duration.ZERO, true, true, CacheKeyPrefix.simple(), SerializationPair.fromSerializer(RedisSerializer.string()), SerializationPair.fromSerializer(RedisSerializer.java(classLoader)), conversionService); }
从上面代码可以看到使用的key前缀是CacheKeyPrefix.simple(),CacheKeyPrefix.simple()的实现如下:
@FunctionalInterface public interface CacheKeyPrefix { /** * Compute the prefix for the actual {@literal key} stored in Redis. * * @param cacheName will never be {@literal null}. * @return never {@literal null}. */ String compute(String cacheName); /** * Creates a default {@link CacheKeyPrefix} scheme that prefixes cache keys with {@code cacheName} followed by double * colons. A cache named {@code myCache} will prefix all cache keys with {@code myCache::}. * * @return the default {@link CacheKeyPrefix} scheme. */ static CacheKeyPrefix simple() { return name -> name + "::"; } }
simple实现的CacheKeyPrefix的compute方法等同于:
String compute(String cacheName){
return cacheName+"::";
}
所以默认的是使用双冒号进行分隔。
但很多情况下,我们并不希望redis的key就是这样的形式,我们可能想:
- 在整个key前加前缀
- 使用不同的分隔符号
怎么做了? 调用CacheKeyPrefix 的定制实现即可。
先来看看CacheKeyPrefix 的唯一接口方法(非静态):
String compute(String cacheName);
也就是说我们可以通过compute来指定需要的实现。
思路有了,那么以下就是实现方式:
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(this.cacheTimeOutHour)).computePrefixWith(cacheName -> cacheName + this.keyPrefix); RedisCacheManager cm=RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(redisCacheConfiguration).build(); cm.setTransactionAware(true);
上文中的关键代码部分:computePrefixWith(cacheName -> cacheName + this.keyPrefix);
我们来看下RedisCacheConfiguration的computePrefixWith的实现代码:
public RedisCacheConfiguration computePrefixWith(CacheKeyPrefix cacheKeyPrefix) { Assert.notNull(cacheKeyPrefix, "Function for computing prefix must not be null!"); return new RedisCacheConfiguration(ttl, cacheNullValues, true, cacheKeyPrefix, keySerializationPair, valueSerializationPair, conversionService); }
所以代码:cacheName -> cacheName + this.keyPrefix 就是为了构建CacheKeyPrefix的compute方法
String compute(String cacheName){ return cacheName+this.keyPrefix; }
如果想加前缀,可以这样:
computePrefixWith(cacheName -> this.getCachePrefix+"->"+cacheName + this.keyPrefix)
这等同于compute方法变为: return this.getCachePrefix+"->"+cacheName + this.keyPrefix
spring 5.1.x后大量使用lambda,如果不熟悉,就无法阅读这个代码。
二、定义key所需要注意的其它方面
1.当多个应用共用一个redis实例的时候,需要注意使用前缀
2.如果有很多值,建议key短一些,并形成一个key的命名文档
以上是关于spring使用RedisCacheManager管理key的一些问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 spring-data 2.0.x 中创建 RedisCacheManager
springboot 中 RedisCacheManager rm = new RedisCacheManager(redisTemplate);我的项目没这个构造
RedisCacheManager 未更新 keyspace_misses