簡述
大家經常會遇到這樣的場景,比如訂單15分鐘內支付,超時未支付則需要取消訂單,這種取消訂單的任務只會執(zhí)行一次。
常規(guī)的做法有使用定時任務輪訓訂單列表,但是假設沒有正在支付的訂單,那么輪訓的定時任務會給占用服務器資源;如果定時任務設置間隔時間較長,則會出現(xiàn)超過15分鐘取消的情況;
其實,可以使用redis訂閱/發(fā)布功能,完美的利用redis的過期key通知服務器,進行超時訂單取消;
配置
在redis.conf配置文件中,修改屬性項
# 原來是""空
notify-keyspace-events "Ex"
重啟redis服務,利用下面的命令,就可以在客戶端監(jiān)聽過期key的事件
// 監(jiān)聽__keyevent@0__:expired通道,過期會接收到通知
> SUBSCRIBE __keyevent@0__:expired
接下來用spring boot實現(xiàn)
1、引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、redis監(jiān)控類
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過期監(jiān)聽
* @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
控制臺輸出結果

image.png
結尾
從上面的例子可以看到,已經成功獲取到了過期的key,接下來我們可以加入訂單編號,進行取消訂單的業(yè)務邏輯;