Springboot+SpringCache+Redisキャッシュの有効期限切れの問題
3730 ワード
Spring+Redisキャッシュについて最近検討したところ、Cacheable注記がメソッドボディに表記されていることが判明してからキャッシュを生成できるが、redisでのキャッシュTILは-1であり、インタフェースから返されたデータがこのキャッシュを適用し続けているため、キャッシュデータが更新できず、ネットワーク上のクエリでは注釈で各メソッドのキャッシュ有効時間をカスタマイズするのに便利な方法がほとんどであることが分かった.コード構成は以下のとおりです.
ソースコードを確認すると、RedisCacheでは3つの注釈の方法に対してそれぞれ異なる方法が実行され、私が使用している@CacheAbleでちょうど使用しているget方法が見つかりました.ソースを貼り付ける
同じputメソッド.
同様に@CachePut注記がインタフェースに表示され、インタフェースデータが正常にキャッシュされ、予め設定されたTIL値が付いていることをテストします.
RedisCacheクラスでは、内部クラスRedisWriteThroughCallBackのdiInRedis()メソッドを使用して入庫されます.このメソッドでは、有効期限が長く設定されています.
明らかにelementではTimeToLive値が定義されていないため、redisライブラリにキャッシュされているデータTILはすべて-1であり、データが期限切れになることはありません.
解決方法:従来のspring bootバージョンは1.4.4-spring-data-redisバージョンは1.7.7、redisバージョンは1.5.15、spring-data-redisバージョンは自動的に1.8.14に切り替えられます.RedisCacheのgetメソッドが
テスト後、キャッシュが正常に期限切れであることが判明
PS:springboot 1.5以降、redis依存中にdataが追加され、
/**
* RedisCacheManager
* @param r
*/
@Autowired
public void configRedisCacheManger(RedisCacheManager r){
r.setDefaultExpiration(100L);
Map expires = Maps.newHashMap();
expires.put("tGet",60L);
//
r.setExpires(expires);
}
@Cacheable(cacheNames = tGet",key = "#xzqh",sync = true)
public Txxx get(String xzqh){
......
}
ソースコードを確認すると、RedisCacheでは3つの注釈の方法に対してそれぞれ異なる方法が実行され、私が使用している@CacheAbleでちょうど使用しているget方法が見つかりました.ソースを貼り付ける
public T get(final Object key, final Callable valueLoader) {
// ,
BinaryRedisCacheElement rce = new BinaryRedisCacheElement(new RedisCacheElement(new RedisCacheKey(key).usePrefix(
cacheMetadata.getKeyPrefix()).withKeySerializer(redisOperations.getKeySerializer()), valueLoader),
cacheValueAccessor);
ValueWrapper val = get(key);
if (val != null) {
return (T) val.get();
}
RedisWriteThroughCallback callback = new RedisWriteThroughCallback(rce, cacheMetadata);
try {
byte[] result = (byte[]) redisOperations.execute(callback);
return (T) (result == null ? null : cacheValueAccessor.deserializeIfNecessary(result));
} catch (RuntimeException e) {
throw CacheValueRetrievalExceptionFactory.INSTANCE.create(key, valueLoader, e);
}
}
同じputメソッド.
@Override
public void put(final Object key, final Object value) {
// expireAfter()
put(new RedisCacheElement(new RedisCacheKey(key).usePrefix(cacheMetadata.getKeyPrefix()).withKeySerializer(
redisOperations.getKeySerializer()), value).expireAfter(cacheMetadata.getDefaultExpiration()));
}
同様に@CachePut注記がインタフェースに表示され、インタフェースデータが正常にキャッシュされ、予め設定されたTIL値が付いていることをテストします.
RedisCacheクラスでは、内部クラスRedisWriteThroughCallBackのdiInRedis()メソッドを使用して入庫されます.このメソッドでは、有効期限が長く設定されています.
protected void processKeyExpiration(RedisCacheElement element, RedisConnection connection) {
if (!element.isEternal()) {
connection.expire(element.getKeyBytes(), element.getTimeToLive());
}
}
明らかにelementではTimeToLive値が定義されていないため、redisライブラリにキャッシュされているデータTILはすべて-1であり、データが期限切れになることはありません.
解決方法:従来のspring bootバージョンは1.4.4-spring-data-redisバージョンは1.7.7、redisバージョンは1.5.15、spring-data-redisバージョンは自動的に1.8.14に切り替えられます.RedisCacheのgetメソッドが
public T get(final Object key, final Callable valueLoader) {
// expireAfter
RedisCacheElement cacheElement = new RedisCacheElement(getRedisCacheKey(key),
new StoreTranslatingCallable(valueLoader)).expireAfter(cacheMetadata.getDefaultExpiration());
BinaryRedisCacheElement rce = new BinaryRedisCacheElement(cacheElement, cacheValueAccessor);
ValueWrapper val = get(key);
if (val != null) {
return (T) val.get();
}
RedisWriteThroughCallback callback = new RedisWriteThroughCallback(rce, cacheMetadata);
try {
byte[] result = (byte[]) redisOperations.execute(callback);
return (T) (result == null ? null : fromStoreValue(cacheValueAccessor.deserializeIfNecessary(result)));
} catch (RuntimeException e) {
throw CacheValueRetrievalExceptionFactory.INSTANCE.create(key, valueLoader, e);
}
}
テスト後、キャッシュが正常に期限切れであることが判明
PS:springboot 1.5以降、redis依存中にdataが追加され、
org.springframework.boot
spring-boot-starter-data-redis