订单未支付30分钟自动取消是如何实现的?
1.借助redis的过期特性
逻辑:
下单时,订单状态是待支付。将订单编号作为key,下单的时间戳作为value,设置过期时间是30分钟。服务器监听redis的key过期事件,如果是订单过期(还会有其他key过期),则修改订单的状态为已取消。当30分钟后未支付则触发redis过期事件,只需修改订单状态即可。若30分钟内支付成功,则需要删除此订单在redis的值。当然,在支付时,需要检查订单是否已超时或已支付。
关键点:
很明确,只需要在应用中添加监听器监听redis过期即可。
首先是配置redis监听器
package com.zxh.example.config;
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;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
继承redis键过期监听器,进行业务处理
package com.zxh.example.config;
import com.zxh.example.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
@Autowired
private OrderService orderService;
public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
// message.toString()可获取失效的key
String expiredKey = message.toString();
log.info("------------------redis key 失效; key = {}", expiredKey);
if (expiredKey.startsWith("order")) {
// 获取订单orderNo
String orderNo = expiredKey.substring(expiredKey.lastIndexOf(":") + 1);
// 将待支付的订单改为已取消(超时未支付)
orderService.orderPaidTimeout(orderNo);
}
}
}
注意:由于存在多个键的过期,故必须对键进行判断,是否是订单超时造成的过期。
2.使用RabbitMQ的过期队列
利用RabbitMQ的过期队列与死信队列,设置消息的存活时间,消息在设置的时间内未被消费,将其投递到死信队列,然后监听死信队列。

浙公网安备 33010602011771号