Spring Data RedisTemplate,设置值时ttl不起作用

Posted

技术标签:

【中文标题】Spring Data RedisTemplate,设置值时ttl不起作用【英文标题】:Spring Data RedisTemplate, ttl is not working when setting a value 【发布时间】:2016-11-24 23:00:12 【问题描述】:

我想为存储在 Redis 中的密钥设置一个 ttl,我通过以下方式完成了该操作:

@Component
public class RedisBetgeniusMarketService implements BetgeniusMarketService 

    private static final int DEFAULT_EVENTS_LIFE_TIME = 240;

    @Value("$redis.events.lifetime")
    private long eventsLifeTime = DEFAULT_EVENTS_LIFE_TIME;

    @Autowired
    private RedisTemplate<String, Market> marketTemplate;

    @Override
    public Market findOne(Integer fixtureId, Long marketId) 
        String key = buildKey(fixtureId, marketId);
        return marketTemplate.boundValueOps(key).get();
    

    @Override
    public void save(Integer fixtureId, Market market) 
        String key = buildKey(fixtureId, market.getId());
        BoundValueOperations<String, Market> boundValueOperations = marketTemplate.boundValueOps(key);
        boundValueOperations.expire(eventsLifeTime, TimeUnit.MINUTES);
        boundValueOperations.set(market);
    

    private String buildKey(Integer fixtureId, Long marketId) 
        return "market:" + fixtureId + ":" + marketId;
    

但是,当我打印创建的密钥的 ttl 时,它等于 -1

请告诉我我做错了什么。

模板bean的配置方式如下:

    @Bean
    public RedisTemplate<String, com.egalacoral.spark.betsync.entity.Market> marketTemplate(RedisConnectionFactory connectionFactory) 
        final RedisTemplate<String, com.egalacoral.spark.betsync.entity.Market> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer(com.egalacoral.spark.betsync.entity.Market.class));
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
     

【问题讨论】:

【参考方案1】:

您需要以不同的顺序调用expire(…)set(…)。 SET 命令删除之前应用的任何超时:

来自http://redis.io/commands/set的文档:

设置键来保存字符串值。如果 key 已经包含一个值,则无论其类型如何,都会将其覆盖。在成功的 SET 操作后,任何先前与该键关联的生存时间都将被丢弃。

在您的情况下,您只需将expire(…)set(…) 的顺序切换为set(…)expire(…)

@Override
public void save(Integer fixtureId, Market market) 
    String key = buildKey(fixtureId, market.getId());
    BoundValueOperations<String, Market> boundValueOperations = marketTemplate.boundValueOps(key);

    boundValueOperations.set(market);
    boundValueOperations.expire(eventsLifeTime, TimeUnit.MINUTES);

除此之外,您可以通过在一次调用中设置值和到期时间来改进代码。 ValueOperations (RedisOperations.opsForValue()) 提供了一个set 方法,通过签名设置密钥和超时

void set(K key, V value, long timeout, TimeUnit unit);

【讨论】:

感谢详细解答。【参考方案2】:

我已经替换了 set()expire() 方法,它开始工作了。

@Override
public void save(Integer fixtureId, Market market) 
    String key = buildKey(fixtureId, market.getId());
    BoundValueOperations<String, Market> boundValueOperations 
                                  = marketTemplate.boundValueOps(key);
    boundValueOperations.set(market);
    boundValueOperations.expire(eventsLifeTime, TimeUnit.MINUTES);

【讨论】:

【参考方案3】:

您也可以尝试使 Redis 中的密钥在给定的特定时间过期

redisTemplate.opsForValue().set(key, value, 1, TimeUnit.MINUTES);

【讨论】:

以上是关于Spring Data RedisTemplate,设置值时ttl不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Spring中使用RedisTemplate操作Redis(spring-data-redis)

Spring中使用RedisTemplate操作Redis(spring-data-redis)

Spring data redis使用java config配置redisTemplate(解决多个redis数据源问题)

Spring data redis使用java config配置redisTemplate(解决多个redis数据源问题)

Shiro 集成Spring 使用 redis时 使用redisTemplate替代jedisPool

spring-data-redis 中使用RedisTemplate操作Redis