1、期望

在一些业务场景中,我们希望在Redis的key过期时,得到通知。

2、开启配置(默认关闭)

在redis的配置文件 redis.conf 中找到"EVENT NOTIFICATION"模块, 解开注释 notify-keyspace-events Ex ;或者在这个模块后增加 notify-keyspace-events Ex 。 来开启key的过期监听

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

@Configuration
public class RedisCacheConfigure extends CachingConfigurerSupport {
    /**
     * key过期事件订阅需要
     *
     * @param redisConnectionFactory
     * @return {@link RedisMessageListenerContainer}
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        return container;
    }
}

3、自定义监听器

该监听器会在key过期时候触发

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import java.nio.charset.StandardCharsets;


@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
        //过期的key
        String key = new String(message.getBody(), StandardCharsets.UTF_8);

        log.info("redis key 过期:pattern={},channel={},key={}", new String(pattern), channel, key);
    }
}

Q.E.D.


曙光在头上,不抬起头,便永远只能看见物质的闪光。