持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
在实际的开发项目中,监听 key 的过期事件,应用非常广泛,例如:优惠券过期,处理各种超时事件等等。
一、使用redis key 过期通知,需开启key过期通知功能:
1、redis-cli客户端,执行:
config set notify-keyspace-events Ex
2、或者直接修改redis server 配置文件,开启keyt过期听通知配置
notify-keyspace-events Ex
二、添加依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
三、添加配置yml文件
#Redis数据库
redis:
database: 1
host: 127.0.0.1
password:
port: 6378
defaultExpireTime: 18000
jedis:
pool:
max-idle: 8
min-idle: 0
max-active: 8
max-wait: -1ms
四、创建配置类
在redis配置文件加入代码:
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
redis监听容器设置连接管理。
五、创建redis过期监听器
//redis消息过期监听器
@Component
@Slf4j
public class RedisExpiredListener extends KeyExpirationEventMessageListener {
public RedisExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
//过期触发方法
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
log.info("cation ---- key {} expired", expiredKey);
}
}
六、测试,使用@PostConstruct注解,在项目启动时候往redis存入key:test:key:TOM HANKS:expired_time,过期事件20S,监听过期事件是否发生。
//测试监听redis的key过期
@PostConstruct
public void init(){
log.info("start init()");
redisTemplate.opsForValue().set("test:key:TOM HANKS:expired_time", "an", 20, TimeUnit.SECONDS);
}
最终,监听事件打印了对应日志信息,说明已经监听到过期事件。
七、另一种实现
创建监听器:
@Component("redisKeyExpirationListener")
@RequiredArgsConstructor
@Slf4j
public class RedisKeyExpirationListener implements MessageListener {
private final StringRedisTemplate redisTemplate;
@Override
public void onMessage(Message message, byte[] bytes) {
// 获取失效的key
String expiredKey = message.toString();
log.info("监听到Redis中:{}过期", expiredKey);
// 指定key 的前缀=test:key:
// 业务处理
}
}
添加配置:
//注册一个redis的消息监听器给spring容器管理
@Configuration
public class RedisConfigListenerContainer {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListener redisKeyExpirationListener){
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(redisKeyExpirationListener, new PatternTopic("__keyevent@1__:expired"));
return container;
}
}
PatternTopic订阅过期事件,
*代表所有库
keyevent@1:expired
__keyevent必须以此开头;
@2 表示[监听]第二个数据库;
:expired 表示过期事件
经验证,同样达到监听效果。
八、注意
过期监听消息中返回的是,过期的键的key值,是没有返回value的。