简述
大家经常会遇到这样的场景,比如订单15分钟内支付,超时未支付则需要取消订单,这种取消订单的任务只会执行一次。
常规的做法有使用定时任务轮训订单列表,但是假设没有正在支付的订单,那么轮训的定时任务会给占用服务器资源;如果定时任务设置间隔时间较长,则会出现超过15分钟取消的情况;
其实,可以使用redis订阅/发布功能,完美的利用redis的过期key通知服务器,进行超时订单取消;
配置
在redis.conf配置文件中,修改属性项
# 原来是""空
notify-keyspace-events "Ex"
重启redis服务,利用下面的命令,就可以在客户端监听过期key的事件
// 监听__keyevent@0__:expired通道,过期会接收到通知
> SUBSCRIBE __keyevent@0__:expired
接下来用spring boot实现
1、引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、redis监控类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* @description: redis Key过期监听
* @author: sxt
*/
public class KeyExpiredListener extends KeyExpirationEventMessageListener {
public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
System.out.println("过期key:" + message.toString());
}
}
3、redis配置类
import com.zy.rabbitmq.base.Listener.KeyExpiredListener;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @description: redis配置类
* @author: sxt
*/
@Configuration
public class RedisConfiguration {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
return redisMessageListenerContainer;
}
@Bean
public KeyExpiredListener keyExpiredListener() {
return new KeyExpiredListener(this.redisMessageListenerContainer());
}
}
4、测试
#set一个有过期时间的key
>set key value ex 5
OK
控制台输出结果
![](https://img.haomeiwen.com/i20212050/88ab2c2e6c2d8011.png)
结尾
从上面的例子可以看到,已经成功获取到了过期的key,接下来我们可以加入订单编号,进行取消订单的业务逻辑;
网友评论