前言
正常情況下,我們是不需要監聽 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,做相應的處理。
參考
Redis key過期監聽
Redis鍵空間通知(Keyspace Notifications)
Redis鍵空間通知