前言
试想一个业务场景,订单超过30分钟未支付需要做自动关单处理,修改订单状态,库存回退等,你怎么实现?方案一:可以使用定时任务扫表,通过支付状态和下单时间来判断是否支付过期。但是这样的方案是非常消耗性能的,因为大部分的定时扫表都是无效的,而且这种定时任务方案对于时间控制并不精确。
类似的业务场景还很多,比如物流自动收货确认,比如某电影上线预约功能的到时提醒等等,对于这些问题有没有比定时任务更优雅的处理方案呢?
可能有朋友了解过可以使用RabbitMQ的延迟队列来实现,这个我后续出RabbitMQ专题的时候再细说一下,这里,Redis监听key过期事件来处理类似的场景。
开启key过期事件
在redis.conf配置文件中有个配置项:notify-keyspace-events " " ,默认是没有key的过期监听的,我们需要将其开启,如下:
这里的 EX代表 expire 和 evicted 过期和驱逐的时间监听 ,注意:改了配置要重启Redis
创建SpringBoot工程
导入Redis依赖
<!--整合Redis , 底层可以用jedis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
然后做yml配置,Redis基本配置
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
password: 123456
jedis:
pool:
max-wait: 2000ms
min-idle: 2
max-idle: 8
这里省略一些不重要的代码
配置Redis监听器
注册 RedisMessageListenerContainer ,为Redis消息侦听器提供异步行为的容器:
@Configuration
public class RedisConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
//Redis消息监听器
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
//设置Redis链接工厂
container.setConnectionFactory(connectionFactory);
return container;
}
}
定义key过期的监听器,通过继承 KeyExpirationEventMessageListener 来完成
//消息过期监听器
@Slf4j
@Component
public class RedisExpireListener extends KeyExpirationEventMessageListener {
public RedisExpireListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
//当消息过期,触发方法
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = message.toString();
System.out.println("Key -> "+expiredKey +"过期了...");
}
}
测试
使用redis-cli 设置一个带过期时间的 key ,如:
等待key过期,观察代码控制台
这样你就可以在key过期之后做一些业务相关的操作啦。
文章到这里就结束了,如果对你有帮助的话,请一定给个好评哦~~