365bet取款要多久-365bet体育365bet官网-365电子游戏

消息队列之支付超时,取消订单(死信队列)

消息队列之支付超时,取消订单(死信队列)

业务场景

创建订单10分钟之后自动支付

订单超时取消

…等等…

实现方式

最简单的方式,定时扫表;例如每分钟扫表一次十分钟之后未支付的订单进行主动支付 ; 优点: 简单 缺点: 每分钟全局扫表,浪费资源,有一分钟延迟

使用RabbitMq 实现 RabbitMq实现延迟队列 优点: 开源,现成的稳定的实现方案; 缺点: RabbitMq是一个消息中间件;延迟队列只是其中一个小功能,如果团队技术栈中本来就是使用RabbitMq那还好,如果不是,那为了使用延迟队列而去部署一套RabbitMq成本有点大;

使用Java中的延迟队列,DelayQueue 优点: java.util.concurrent包下一个延迟队列,简单易用;拿来即用 缺点: 单机、不能持久化、宕机任务丢失等等;

本文在这里选用rabbitmq死信队列的方式实现支付超时,取消订单。

1.配置消息队列处开启手动ack 2.定义一个生产者

/**

* 生产者 ->生产消息

* 作者:Chris On 2020/09/01 10:44

* 这里声明的amqpTemplate接口,这个接口包含了发送和接收消息的一般操作,换种说法,它不是某个实现所专有的,所以AMQP存在于名称里。这个接口的实现与AMQP协议的实现紧密关联。

* this.amqpTemplate.convertAndSend的第一个参数为延迟交换机的名称,第二个为延时消费routing-key,第三个参数为order操作对象,第四个参数为消息

*/

@Component

@Slf4j

public class DelaySender {

// AMQP 高级消息队列协议

@Autowired

private AmqpTemplate amqpTemplate;

public void sendDelay(ConcurrentHashMap order) {

log.info("【订单生成时间】" + new Date().toString() +"【1分钟后检查订单是否已经支付】" + order.toString() );

this.amqpTemplate.convertAndSend(DelayRabbitConfig.ORDER_DELAY_EXCHANGE, DelayRabbitConfig.ORDER_DELAY_ROUTING_KEY, order, message -> {

// 如果配置了 params.put("x-message-ttl", 5 * 1000); 那么这一句也可以省略,具体根据业务需要是声明 Queue 的时候就指定好延迟时间还是在发送自己控制时间

message.getMessageProperties().setExpiration(1 * 1000 * 60 + "");

return message;

});

}

}

3.消费者->消费消息,由于我们在配置处开启了手动ack,这里消费者消费到消息后要进行应答,否则消息服务器会以为这条消息没处理掉

/**

* 接收者 ->消费者

* By Chris On 2020/09/01 10:37

*/

@Component

@Slf4j

public class DelayReceiver {

@Resource

private MyOrderMasterMapper myOrderMasterMapper;

@Autowired

private RedisUtil redisUtil;

@Autowired

private SkuMapper skuMapper;

@RabbitListener(queues =