悠哉杂学 - 消息队列
type: channel
link: https://uinit.cn/index.php/tag/消息队列/
items: 生成订单30分钟未支付，则自动取消，该怎么实现？

生成订单30分钟未支付，则自动取消，该怎么实现？
type: item
date: 2021-09-06T21:46:00+08:00
description: 在开发中，往往会遇到一些关于延时任务的需求。例如：生成订单30分钟未支付，则自动取消生成订单60秒后,给用户发短信对上述的任务，我们给一个专业的名字来形容，那就是延时任务。那么这里就会产生一个问题，这个延时任务和定时任务的区别究竟在哪里呢？一共有如下几点区别定时任务有明确的触发时间，延时任务没有定时任务有执行周期，而延时任务在某事件触发后一段时间内执行，没有执行周期定时任务一般执行的是批处理操作是多个任务，而延时任务一般是单个任务下面，我们以判断订单是否超时为例，进行方案分析方案分析(1)数据库轮询思路该方案通常是在小型项目中使用，即通过一个线程定时的去扫描数据库，通过订单时间来判断是否有超时的订单，然后进行update或delete等操作实现博主当年早期是用quartz来实现的(实习那会的事)，简单介绍一下maven项目引入一个依赖如下所示 org.quartz-scheduler quartz 2.2.2 调用Demo类MyJob如下所示package com.rjzheng.delay1; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; public class MyJob implements Job { public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("要去数据库扫描啦。。。"); } public static void main(String[] args) throws Exception { // 创建任务 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(); } } 运行代码，可发现每隔3秒，输出如下要去数据库扫描啦。。。优缺点优点:简单易行，支持集群操作缺点:(1)对服务器内存消耗大(2)存在延迟，比如你每隔3分钟扫描一次，那最坏的延迟时间就是3分钟(3)假设你的订单有几千万条，每隔几分钟这样扫描一次，数据库损耗极大(2)JDK的延迟队列思路该方案是利用JDK自带的DelayQueue来实现，这是一个无界阻塞队列，该队列只有在延迟期满的时候才能从中获取元素，放入DelayQueue中的对象，是必须实现Delayed接口的。DelayedQueue实现工作流程如下图所示其中Poll():获取并移除队列的超时元素，没有则返回空take():获取并移除队列的超时元素，如果没有则wait当前线程，直到有元素满足超时条件，返回结果。实现定义一个类OrderDelay实现Delayed，代码如下package com.rjzheng.delay2; import java.util.concurrent.Delayed; import java.util.concu…