Redis中监听key过期通知
前言
正常情况下,我们是不需要监听 key 是否过期的,毕竟项目中 key 数量可能成千上万,要监听的话很耗费服务器资源。但是如果项目中 key 数量很少,且我们要在指定 key 过期时告警,这种场景下就是合适的。
使用
服务器开启配置
redis.conf 文件
notify-keyspace-events Ex
默认配置为 "",表示未开启,Ex 表示 key 过期通知。
K Keyspace events, published with __keyspace@<db>__ prefix.(键空间通知)
E Keyevent events, published with __keyevent@<db>__ prefix.(键事件通知)
g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...(通用命令(非类型特定的),如DEL、EXPIRE、RENAME)
$ String commands(字符串命令)
l List commands(列表命令)
s Set commands(集合命令)
h Hash commands(哈希命令)
z Sorted set commands(有序集合命令)
x Expired events (events generated every time a key expires)(过期事件(每次密钥过期时生成的事件))
e Evicted events (events generated when a key is evicted for maxmemory)(驱逐事件(当为maxmemory退出一个键时生成的事件))
t Stream commands(Stream命令)
d Module key type events(模块key类型事件)
m Key-miss events (Note: It is not included in the 'A' class)(Key-miss事件(当访问不存在的键时通知,不包含在A中))
A Alias for g$lshzxetd(g$lshzxetd的别名都可用A表示), so that the "AKE" string means all the events(Except key-miss events which are excluded from 'A' due to their unique nature)(用“AKE”可表示所有事件通知,除了特殊的Key-miss事件)
代码配置
在 SpringBoot 项目中使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
host: ip
port: 6379
password: xxx
具体代码如下
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
// redis 消息订阅(监听者)容器
RedisMessageListenerContainer messageListenerContainer = new RedisMessageListenerContainer();
messageListenerContainer.setConnectionFactory(redisConnectionFactory);
return messageListenerContainer;
}
@Bean
public CustomRedisKeyExpirationListener customRedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
return new CustomRedisKeyExpirationListener(listenerContainer);
}
public static class CustomRedisKeyExpirationListener extends KeyExpirationEventMessageListener {
public CustomRedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
protected void doHandleMessage(Message message) {
String expiredKey = message.toString();
System.out.println("监听到过期key: " + expiredKey);
}
}
}
通过 继承 KeyExpirationEventMessageListener 来实现,如果我们服务器没有配置 notify-keyspace-events,spring 会自动配置其值为 EA,具体参考 KeyspaceEventMessageListener 的 init() 方法。
监听器的底层原理为 redis 的发布订阅功能,当有 key 过期时,会向 keyevent@*:expired 这个 topic 发送消息,我们客户端监听此 topic,得到过期的 key,做相应的处理。