Springフレームワークは、様々なインメモリキャッシュを効果的に管理する機能を提供しています。
一般的なインメモリキャッシュ実装には、RedisやEhcacheなどがありますが、本稿では特に容易に利用できるRedisに焦点を当てて解説します。
Springはorg.springframework.cache.Cacheとorg.springframework.cache.CacheManagerという二つの主要インターフェースを通じてキャッシュを管理します。
Redisのキャッシュ実装クラスはRedisCacheManagerであり、その階層構造は以下のようになっています:
object
<-AbstractCacheManager=>(CacheManager, InitializingBean)
<-AbstractTransactionSupportingCacheManager
<-RedisCacheManager
この構造から、RedisCacheManagerがCacheManagerインターフェースを実装していることがわかります。
一、Redisキーのカスタマイズ方法
デフォルトの方式でRedisCacheManagerを登録する場合、以下のようなコードになります:
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(this.cacheTimeOutHour))
例えば、以下のようなアノテーションを使用した場合:
@Cacheable(value="getUserPoJoById",key="#userId")
生成されるRedisキーは以下のような形式になります:
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);
}
上記のコードから、使用されているキープレフィックスが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キーをこの形式で使用したくない場合があります。以下のような要件があるかもしれません:
- キー全体にプレフィックスを追加する
- 異なるセパレータを使用する
これを実現するには、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以降、ラムダ式が広く使用されているため、このコードを理解するにはラムダ式の知識が必要です。
二、キー定義におけるその他の注意点
1. 複数のアプリケーションで同一のRedisインスタンスを共有する場合、プレフィックスの使用に注意が必要です
2. 多くの値を格納する場合、キーは短くし、キーの命名規約を文書化することが推奨されます