1、简介 {#1简介}
在本教程中,我们将学习如何在 Spring Data Redis 中配置 key 的过期时间。
2、项目设置 {#2项目设置}
假设我们有一个整合了 spring data redis 的 spring boot 项目,我们打算使用 redis 来管理用户的会话(Session
)。
2.1、依赖 {#21依赖}
首先,在 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-redis
和 lettuce-core
。
2.2、Redis 配置 {#22redis-配置}
其次,添加 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、Model {#23model}
第三,创建 Session
model:
@RedisHash
public class Session {
@Id
private String id;
private Long expirationInSeconds;
}
2.4、Redis Repository {#24redis-repository}
最后,创建 SessionRepository
,它提供与 Redis 的交互,以管理我们的 Session
实体:
public interface SessionRepository extends CrudRepository<Session, String> {}
3、设置 TTL 的方法 {#3设置-ttl-的方法}
我们将介绍三种设置 TTL 的方法。
3.1、使用 @RedisHash
{#31使用-redishash}
从最简单的开始。@RedisHash
允许我们为其 timeToLive
属性提供一个值:
@RedisHash(timeToLive = 60L)
public class Session {
@Id
private String id;
private Long expirationInSeconds;
}
它以秒为单位取值。在上例中,我们将过期时间设置为 60 秒。当我们想为所有 Session
对象提供一个恒定值 TTL 时,这种方法非常有用。
3.2、使用 @TimeToLive
{#32使用-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
{#33使用-keyspacesettings}
接下来,使用 KeyspaceSettings
设置 TTL。Keyspace 定义了用于创建 Redis Hash 实际 key 的前缀。现在,让我们为 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、比较 {#4比较}
最后,让我们比较一下我们看过的三种方法,看看什么时候该使用哪一种。
@RedisHash
和 KeyspaceSettings
都允许我们一次性为所有实体实例(Session
)设置 TTL。而,@TimeToLive
允许我们为每个实体实例动态设置 TTL。
KeyspaceSettings
提供了一种方法,可以在一个地方设置多个实体的默认 TTL。而 @TimeToLive
和 @RedisHash
则需要在每个实体类中进行设置。
@TimeToLive
的优先级最高,其次是 @RedisHash
,最后是 KeyspaceSettings
。
5、Redis Key 过期事件 {#5redis-key-过期事件}
设置了 key 的过期时间后,我们可能还会对"过期事件"何时发生感兴趣。为此,框架提供了 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());
}
}
}
现在我们可以知道 Session
何时过期,可以在过期时执行一些其他逻辑:
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、总结 {#6总结}
在本文中,我们介绍了通过 Spring Data Redis 设置 Redis TTL 的各种方法,以及如何监听 key 过期事件(RedisKeyExpiredEvent
)。
参考:https://www.baeldung.com/spring-data-redis-ttl