概述

在这个简短教程中,我们将探讨如何在Spring Data Redis中配置键过期时间。

2. 设置

首先,我们创建一个基于Spring Boot的API,用于管理由Redis持久化的会话资源。要做到这一点,我们需要四个主要步骤。有关更详细的设置,请参阅我们的指南:Spring Data Redis教程

2.1. 依赖项

首先,在pom.xml中添加以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>3.0.4</version>
</dependency>

spring-boot-starter-data-redis将隐式添加spring-data-redislettuce-core

2.2. Redis配置

其次,让我们添加RedisTemplate配置:

@Configuration
public class RedisConfiguration {

    @Bean
    public RedisTemplate<String, Session> getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Session> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        return redisTemplate;
    }
}

2.3. 模型

第三步,创建我们的会话模型:

@RedisHash
public class Session {
    @Id
    private String id;
    private Long expirationInSeconds;
}

2.4. Redis仓库

最后,创建SessionRepository,它提供与Redis的交互,以管理我们的Session实体:

public interface SessionRepository extends CrudRepository<Session, String> {}

3. 方法

我们将探讨三种设置TTL的方法。

3.1. 使用@RedisHash

我们从最简单的方法开始。@RedisHash允许我们为其timeToLive属性提供一个值:

@RedisHash(timeToLive = 60L)
public class Session {
    @Id
    private String id;
    private Long expirationInSeconds;
}

它以秒为单位接受值。 在上面的例子中,我们将过期时间设置为60秒。这种方法适用于当我们希望为所有Session对象提供恒定的TTL值时。也可以指定默认TTL。

3.2. 使用@TimeToLive

在前一种方法中,我们可以为所有Session对象设置相同的恒定TTL。接下来的方法更具动态性。使用@TimeToLive,我们可以注解任何数值属性或返回数值值的方法来设置TTL:

@RedisHash(timeToLive = 60L)
public class Session {
    @Id
    private String id;
    @TimeToLive
    private Long expirationInSeconds;
}

这允许我们为每个Session对象动态设置TTL。与前一种方法一样,TTL也是以秒为单位。@TimeToLive的值优先于@RedisHash(timeToLive)

3.3. 使用KeyspaceSettings

接下来的方法是使用KeyspaceSettings设置TTL。键空间定义了实际用于Redis哈希键创建的前缀。现在,让我们为Session类定义KeyspaceSettings

@Configuration
@EnableRedisRepositories(keyspaceConfiguration = RedisConfiguration.MyKeyspaceConfiguration.class)
public class RedisConfiguration {

    // Other configurations omitted

    public static class MyKeyspaceConfiguration extends KeyspaceConfiguration {

        @Override
        protected Iterable<KeyspaceSettings> initialConfiguration() {
            KeyspaceSettings keyspaceSettings = new KeyspaceSettings(Session.class, "session");
            keyspaceSettings.setTimeToLive(60L);
            return Collections.singleton(keyspaceSettings);
        }
    }
}

就像前面的方法一样,我们也在秒为单位指定了TTL。这种方法与@RedisHash类似。此外,如果我们不希望使用@EnableRepositories,可以更程序化地设置它:

@Configuration
public class RedisConfiguration {

    // Other configurations omitted

    @Bean
    public RedisMappingContext keyValueMappingContext() {
        return new RedisMappingContext(new MappingConfiguration(new IndexConfiguration(), new MyKeyspaceConfiguration()));
    }

    public static class MyKeyspaceConfiguration extends KeyspaceConfiguration {

        @Override
        protected Iterable<KeyspaceSettings> initialConfiguration() {
            KeyspaceSettings keyspaceSettings = new KeyspaceSettings(Session.class, "session");
            keyspaceSettings.setTimeToLive(60L);
            return Collections.singleton(keyspaceSettings);
        }
    }
}

4. 比较

最后,让我们比较我们研究的三种方法,并确定何时使用它们。

@RedisHashKeyspaceSettings都允许我们为所有实体实例(例如Session)设置TTL一次。而@TimeToLive则允许我们为每个实体实例动态设置TTL。

KeyspaceSettings提供了一种在一个位置为多个实体设置默认TTL的方法。相比之下,@TimeToLive@RedisHash需要在每个实体类文件中进行设置。

@TimeToLive具有最高的优先级,其次是@RedisHash,最后是KeyspaceSettings

5. Redis键过期事件

使用这些设置Redis键过期时间的方法后,我们可能还对何时发生此类事件感兴趣。为此,我们有RedisKeyExpiredEvent。让我们设置一个EventListener来捕获RedisKeyExpiredEvent

@Configuration
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
@Slf4j
public class RedisConfiguration {
    // Other configurations omitted

    @Component
    public static class SessionExpiredEventListener {
        @EventListener
        public void handleRedisKeyExpiredEvent(RedisKeyExpiredEvent<Session> event) {
            Session expiredSession = (Session) event.getValue();
            assert expiredSession != null;
            log.info("Session with key={} has expired", expiredSession.getId());
        }
    }
}

现在,我们将能够知道何时会话过期,并在需要时采取行动:

2023-02-10T15:13:38.626+05:30  INFO 16874 --- [enerContainer-1] c.b.s.config.RedisConfiguration:
  Session with key=edbd98e9-7b50-45d8-9cf4-9c621899e213 has expired

6. 结论

在这篇文章中,我们探讨了通过Spring Data Redis设置Redis TTL的各种方法。最后,我们讨论了RedisKeyExpiredEvent以及如何处理过期事件。

如往常一样,代码可在GitHub上找到。