redis沒法設置TTL的排查

不再相信網上的鬼才配置了java

這裏指的是Spring Cache的配置redis

以前找來的配置以下緩存

@Bean(name="redisCache")
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
        //設置默認超過時時間是1天 // 我差點就信了
        defaultCacheConfig.entryTtl(Duration.ofDays(1));
        //初始化RedisCacheManager
        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
        return cacheManager;
    }

可是不管如何ttl查詢,對應緩存的key都會返回-1bash

127.0.0.1:6379> ttl user::userID21
(integer) -1
127.0.0.1:6379> ttl problems::getConsequentProblems::1:20
(integer) -1

網上找了一遍問題,好像都沒這問題。。。本身找吧測試

測試ui

直接在Bean裝載時觀察是否有效this

@Bean(name="redisCache")
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
         defaultCacheConfig.entryTtl(Duration.ofDays(1));
        
        //////
        System.out.println("你的TTL:"+defaultCacheConfig.getTtl());
        
        
        RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
        return cacheManager;
    }

輸出部分code

你的TTL:PT0S

觀察Duration的toString方法部分get

if (this == ZERO) {
            return "PT0S";
        }

這就十分酸爽了。。源碼

找坑點:

順着網線(指源碼)找了這麼一個構造

static RedisCacheWriter nonLockingRedisCacheWriter(RedisConnectionFactory connectionFactory) {

        Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");

        return new DefaultRedisCacheWriter(connectionFactory);
    }

// ...忽略


    DefaultRedisCacheWriter(RedisConnectionFactory connectionFactory) {
        this(connectionFactory, Duration.ZERO);
    }

不過發現Duration.ZERO指的是SleepTime,排除

DefaultRedisCacheWriter(RedisConnectionFactory connectionFactory, Duration sleepTime)

而RedisCacheManager的配置是依賴於RedisCacheConfiguration的

其中ttl部分只會在這裏出現

public class RedisCacheConfiguration {

    private final Duration ttl;
    private final boolean cacheNullValues;
    private final CacheKeyPrefix keyPrefix;
    
    //.....

    @SuppressWarnings("unchecked")
    private RedisCacheConfiguration(Duration ttl, Boolean cacheNullValues, Boolean usePrefix, CacheKeyPrefix keyPrefix,
            SerializationPair<String> keySerializationPair, SerializationPair<?> valueSerializationPair,
            ConversionService conversionService) {

        this.ttl = ttl;
        
        //....

至少證實構造方面沒坑,TTL確實依賴於Configuration

觀察可疑部分

public RedisCacheConfiguration entryTtl(Duration ttl) {

        Assert.notNull(ttl, "TTL duration must not be null!");

        return new RedisCacheConfiguration(ttl, cacheNullValues, usePrefix, keyPrefix, keySerializationPair,
                valueSerializationPair, conversionService);
    }

發現是Builder形式

那麼從新=一下就應該沒問題了

defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofDays(1));
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> keys *
1) "user::getUserByUserID::21"
2) "problems::getConsequentProblems::1:20"
127.0.0.1:6379> ttl problems::getConsequentProblems::1:20
(integer) 86387
相關文章
相關標籤/搜索