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就是這樣的形式,我們可能想:

  1. 在整個key前加前綴
  2. 使用不同的分隔符號

怎么做了? 調用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的命名文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM