Redis key 过期监听实现

1.技术背景,想知道 redis 设置了TTL时间的key 过期,且有后续的业务处理的场景可以使用。

bug点:

使用redis 缓存失效监听会有一定的延迟, 过期事件是在redis服务器删除键的时候生成的,而不是在理论上生存时间到达0值得时候生成的。

搭建:

1.前置条件为 redis服务器端开启了事件通知。配置文件redis.conf文件中 开启相关配置。

默认情况下redis是未开启事件通知的。

bash 复制代码
############################# EVENT NOTIFICATION ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at https://redis.io/topics/notifications
#
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  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, ...
#  $     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)
#  t     Stream commands
#  d     Module key type events
#  m     Key-miss events (Note: It is not included in the 'A' class)
#  A     Alias for g$lshzxetd, so that the "AKE" string means all the events
#        (Except key-miss events which are excluded from 'A' due to their
#         unique nature).
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
#  notify-keyspace-events ""
# 配置文件修改项
notify-keyspace-events "Ex" 

可直接修改 notify-keyspace-events "Ex" 即为开启了rediss 事件监听,然后重启redis 服务(或者使用命令的形式,不需要重启redis服务)。不同key 类型的监听见上文档。

2.项目中编写相关的监听程序(前置条件,redis已经集成进项目里了)

java 复制代码
import com.jinyi.up.user.listener.RedisKeyExpirationListener;
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.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
/**
 * spring容器 里通过 java配置方式注入RedisMessageListenerContainer 和  KeyExpirationEventMessageListener的实现类
 * @author jinyi
 * @date 2023/11/25 16:39
 * @desc
 */
@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer listenerContainer(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer listenerContainer = new RedisMessageListenerContainer();
        listenerContainer.setConnectionFactory(connectionFactory);
        return listenerContainer;
    }

    @Bean
    KeyExpirationEventMessageListener redisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        return new RedisKeyExpirationListener(listenerContainer);
    }

}
java 复制代码
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 org.springframework.stereotype.Component;

/**
 * 使用redis 缓存失效监听会有一定的延迟, 过期事件是在redis服务器删除键的时候生成的,而不是在理论上生存时间到达0值得时候生成的,
 *
 * @author jinyi
 * @date 2023/11/25 16:40
 * @desc
 */
@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

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

    /**
     * 针对redis数据失效事件,进行数据处理
     *
     * @param message key的信息,并不包含缓存值。
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        //获得失效的key
        log.info("KeyExpiration key:" + message);
        //todo 后续的业务处理
    }

}
相关推荐
麓殇⊙19 分钟前
redisson锁的可重入、可重试、超时续约原理详解
redis·分布式锁
jstart千语21 分钟前
【Redisson】锁可重入原理
redis·分布式·redisson
粟悟饭&龟波功26 分钟前
Java—— ArrayList 和 LinkedList 详解
java·开发语言
冷雨夜中漫步32 分钟前
Java中如何使用lambda表达式分类groupby
java·开发语言·windows·llama
在未来等你32 分钟前
互联网大厂Java求职面试:云原生架构与微服务设计中的复杂挑战
java·微服务·ai·云原生·秒杀系统·rag·分布式系统
浮游本尊36 分钟前
Java学习第4天 - 异常处理与集合框架
java
知其然亦知其所以然1 小时前
Spring AI 入门实战:我用七个关键词,彻底搞懂了它的核心概念!
java·后端·spring
码农颜1 小时前
java 设计模式_行为型_19命令模式
java·设计模式·命令模式
魔镜魔镜_谁是世界上最漂亮的小仙女1 小时前
java-JDBC
java·后端
gorgor在码农1 小时前
Spring Boot多数据源切换:三种实现方式详解与实战
java·spring boot·后端·mybatis·mybatis plus·多数据源切换