redis无法设置TTL的排查

再也不相信网上的鬼才配置了

这里指的是Spring Cache的配置

之前找来的配置如下

    @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都会返回-1

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

网上找了一遍问题,好像都没这问题。。。自己找吧

找坑点:

顺着网线(指源码)找了这么一个构造

    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

测试

直接在Bean装载时观察是否有效

    @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;
    }

输出部分

你的TTL:PT0S

观察Duration的toString方法部分

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

这就十分酸爽了。。

观察可疑部分

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
上一篇:域名解析


下一篇:ACL访问控列表之标准版