Redis中監聽key過期通知

strongmore發表於2024-04-03

前言

正常情況下,我們是不需要監聽 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鍵空間通知

相關文章