【问题标题】:Spring Data RedisTemplate, ttl is not working when setting a valueSpring Data RedisTemplate,设置值时ttl不起作用
【发布时间】: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;
    } 

【问题讨论】:

    标签: redis spring-data-redis


    【解决方案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);
      

      【讨论】:

        猜你喜欢
        • 2017-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-06
        • 2014-08-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多