前言
试想一个业务场景,订单超过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: 0host: 127.0.0.1port: 6379password: 123456jedis:pool:max-wait: 2000msmin-idle: 2max-idle: 8
这里省略一些不重要的代码
配置Redis监听器
注册 RedisMessageListenerContainer ,为Redis消息侦听器提供异步行为的容器:
@Configuration
public class RedisConfig {@BeanRedisMessageListenerContainer 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);}//当消息过期,触发方法@Overridepublic void onMessage(Message message, byte[] pattern) {String expiredKey = message.toString();System.out.println("Key -> "+expiredKey +"过期了...");}
}
测试
使用redis-cli 设置一个带过期时间的 key ,如:
等待key过期,观察代码控制台
这样你就可以在key过期之后做一些业务相关的操作啦。
文章到这里就结束了,如果对你有帮助的话,请一定给个好评哦~~