生成订单30分钟未支付,则自动取消,该怎么实现?

1 数据库轮询

通常是在小型项目中使用,即通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行update或delete等操作.

用quartz来实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 创建任务
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1", "group1").build();

// 创建触发器 每3秒钟执行一次
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "group3")
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(3).repeatForever())
.build();

Scheduler scheduler = new StdSchedulerFactory().getScheduler();
// 将任务及其触发器放入调度器
scheduler.scheduleJob(jobDetail, trigger);
// 调度器开始调度任务
scheduler.start();

2 JDK的延迟队列

利用JDK自带的DelayQueue来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象,是必须实现Delayed接口的。

3 时间轮算法

1
2
3
4
5
6
7
public static void main(String[] argv) {
//自定义TimerTask
MyTimerTask timerTask = new MyTimerTask(true);
Timer timer = new HashedWheelTimer();
//5s后将会执行timerTask
timer.newTimeout(timerTask, 5, TimeUnit.SECONDS);
}

优点:效率高,任务触发时间延迟时间比delayQueue低,代码复杂度比delayQueue低。

缺点:

  • 服务器重启后,数据全部消失
  • 集群扩展相当麻烦
  • 因为内存条件限制的原因,比如下单未付款的订单数太多,那么很容易就出现OOM异常

4 redis缓存

该方案使用redis的Keyspace Notifications,中文翻译就是键空间机制,就是利用该机制可以在key失效之后,提供一个回调,实际上是redis会给客户端发送一个消息。

5 使用消息队列

5.1 rabbitmq

死信队列和延迟插件方法。

可以采用rabbitMQ的延时队列。RabbitMQ具有以下两个特性,可以实现延迟队列:

  • RabbitMQ可以针对Queue和Message设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为dead letter
  • lRabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,用来控制队列内出现了deadletter,则按照这两个参数重新路由。

优点:高效,可以利用mq的横向扩展,持久化消息增加了可靠性

缺点:依赖mq,增加系统的复杂性和成本

5.2 rocketmq

延时消息用于指定消息发送到消息队列RocketMQ版的服务端后,延时一段时间才被投递到客户端进行消费(例如3秒后才被消费),适用于解决一些消息生产和消费有时间窗口要求的场景,或者通过消息触发延迟任务的场景,类似于延迟队列。

1
2
3
4
5
6
// 延时消息,在指定延迟时间(当前时间之后)进行投递。最大可设置延迟40天投递,单位毫秒(ms)。
// 以下示例表示消息在3秒后投递。
long delayTime = System.currentTimeMillis() + 3000;
// 设置消息需要被投递的时间。
msg.setStartDeliverTime(delayTime);
SendResult sendResult = producer.send(msg);

参考文档:

https://mp.weixin.qq.com/s/J6jb_Dt3C49CIjYBTrN4gQ

源码

https://github.com/leellun/javasvc-learn/tree/main/svc-delaytask

rabbitmq死信队列:

https://github.com/leellun/rabbitmq-learn/tree/main/RabbitMQDemo/src/main/java/com/newland/rabbitmq/advance/rabbitexchnage02


生成订单30分钟未支付,则自动取消,该怎么实现?
https://leellun.github.io/2022/03/24/业务场景/2022-03-24-生成订单30分钟未支付,则自动取消,该怎么实现?/
作者
leellun
发布于
2022年3月24日
许可协议