一.场景

生活中,12306购票、京东、淘宝购物下单,都会遇到请在30分钟内进行支付的场景,互联网电商项目的订单系统都需要解决订单超时问题。

无独有偶,订单超时业务场景,非常符合“在一段时间之后,完成一个工作任务”的需求。今天,抽时间给大家总结了几种订单超时未支付自动关闭的实现方案。

二.实现方案

1、定时任务

数据库轮询方式,实现思路比较简单。启动一个定时任务,每隔一定时间扫描订单表,物理逻辑做处理,这种处理方式只是适合比较小而简单的项目。

假设订单表结构为:

t_order(订单Id、订单状态status、创建时间utc_time)

然后,定时任务每隔一个5min(自己设定时间)扫描数据库,通过下单时间和状态判断订单是否30分钟还未支付:

select orderId from t_order where 当前时间-utc_time > 30min and status = "未支付";

然后,关闭订单:

update t_order set status = "订单取消" where orderId in(超时订单id);

如果数据量很大,需要分页查询,分页update会是一个for循环。

优点:

实现简单,无技术难点,异常恢复,支持分布式/集群环境。

缺点:

影响数据库性能,时效性差,效率低。

2、 被动取消

这种实现方案和懒加载的思想一致,就是被动的取消订单。只有当用户查询订单消息时,再判断订单是否超时,如果超时再进行超时逻辑的处理。但是这种方式依赖于用户的查询操作触发,也就说如果用户不进行订单查询,该订单就永远不会被取消,这就会导致库存可能始终被占用。

所以,在实际项目中,很可能是被动取消 + 定时任务的组合实现方式解决超时订单。这种情况下定时任务的执行时间可以设置稍微“长”一点。

优点:

实现思路简单。

缺点:

(1)会产生额外影响,比如统计,订单,库存等;

(2)影响用户体验,用户打开订单列表可能需要处理大量数据,影响显示的实时性。

3、延迟任务

JDK的延时队列

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

// 定义一个Delay,放入到DelayQueue队列中,向队列中插入一个元素(延时任务)"以毫秒为单位的延迟"
taskService.addTask(new CancelOrderTask(outTradeNo, 1800000));
public class CancelOrderTask extends Task {private final Log logger = LogFactory.getLog(GenerateWalletTask.class);private String outTradeNo;public CancelOrderTask(String outTradeNo, long delayInMilliseconds) {super("CancelOrderTask-" + outTradeNo, delayInMilliseconds);this.outTradeNo = outTradeNo;}// 执行任务@Overridepublic void run() {// 如果存在则取消订单,恢复对应库存}
}
public abstract class Task implements Delayed, Runnable{private String id = "";private long start = 0;public Task(String id, long delayInMilliseconds){this.id = id;this.start = System.currentTimeMillis() + delayInMilliseconds;}public String getId() {return id;}@Overridepublic long getDelay(TimeUnit unit) {long diff = this.start - System.currentTimeMillis();return unit.convert(diff, TimeUnit.MILLISECONDS);}@Overridepublic int compareTo(Delayed o) {return Ints.saturatedCast(this.start - ((Task) o).start);}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null) return false;if (!(o instanceof Task)) {return false;}Task t = (Task)o;return this.id.equals(t.getId());}@Overridepublic int hashCode() {return this.id.hashCode();}
}
@Component
public class TaskService {private TaskService taskService;private DelayQueue<Task> delayQueue = new DelayQueue<Task>();@PostConstructprivate void init() {taskService = this;Executors.newSingleThreadExecutor().execute(new Runnable() {@Overridepublic void run() {while (true) {try {Task task = delayQueue.take();task.run();} catch (Exception e) {e.printStackTrace();}}}});}public void addTask(Task task) {if (delayQueue.contains(task)) {return;}delayQueue.add(task);}public void removeTask(Task task) {delayQueue.remove(task);}}

优点:

实现简单,性能较好。

缺点:

异常恢复困难,分布式/集群实现困难。

青年人的责任重大!努力吧...

订单超时未支付自动关闭实现方案相关推荐

  1. 拼夕夕订单超时未支付自动关闭实现方案!

    " 在开发中,往往会遇到一些关于延时任务的需求.例如:生成订单 30 分钟未支付,则自动取消:生成订单 60 秒后,给用户发短信. 对上述的任务,我们给一个专业的名字来形容,那就是延时任务. ...

  2. 订单超时未支付自动关闭的几种实现方案

    做电商,就会遇到订单超时问题,而且还经常被拿来面试提问! 今天,周末放假,抽时间给大家总结了几种订单超时未支付自动关闭的实现方案.同时,我手机还有几套电商类从零架构到实现的视频教程,如有需要,可以加我 ...

  3. 订单超时未支付的解决方案

    订单超时未支付的解决方案 定时任务实现 被动取消 JDK的延迟队列 代码演示 时间轮算法 代码演示 Redis zset 实现延迟任务 代码演示 MQ 延时消息 代码演示 写在最后 在前面的文章 第三 ...

  4. 订单超时未支付自动取消5种实现方案

    大家好,我是宝哥! 前言 在开发中,往往会遇到一些关于延时任务的需求.比如最近大家都在忙抢回家的火车票,当你下了一个订单没有支付时,会有一个倒计时,提示你半小时之内支付,否则会自动取消.这样的场景是如 ...

  5. rabbitMQ实现订单超时未支付自动取消订单

    前期准备 下面展示一些 内联代码片. 1.配置文件,导入jar包 server:port: 8983 spring:application:name: API-RABBITMQdatasource:t ...

  6. 订单超时未支付自动取消8种实现方案

    定时轮询 数据库定时轮询方式,实现思路比较简单.启动一个定时任务,每隔一定时间扫描订单表,查询到超时订单就取消. 优点:实现简单. 缺点:轮询时间间隔不好确定,占用服务器资源,影响数据库性能. 惰性取 ...

  7. Java秒杀系统实战系列~RabbitMQ死信队列处理超时未支付的订单(转)

    转自: https://juejin.cn/post/6844903903130042376 文末有源代码,非常棒 摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十篇,本篇 ...

  8. 订单超时自动取消3种方案——我们用这种!

    大家好,大家对电商购物应该都比较熟悉了,我们应该注意到,在下单之后,通常会有一个倒计时,如果超过支付时间,订单就会被自动取消. 下单 今天,我们来聊聊订单超时未支付自动取消的几种方案. 1.定时任务 ...

  9. TP5.1 实现超时未支付订单自动关闭

    对于这个需求,我以前写过Laravel版本的.今天想在TP5.1中实现这个功能,但是网上基本没什么教程可供参考,所以写篇文章仅供大家学习. 一.前台 1.先来加载订单确认页面 当下单成功后,通过 js ...

  10. 1.超时未支付订单处理

    1.超时未支付订单处理 1.1 需求分析 超过限定时间并未支付的订单,我们需要进行超时订单的处理:先调用微信支付api,查询该订单的支付状态.如果未支付调用关闭订单的api,并修改订单状态为已关闭,并 ...

最新文章

  1. 设计模式笔记(9)---组合模式(结构型)
  2. 利用BP神经网络教计算机识别语音特征信号(代码部分SS)
  3. 【IDAX投研中心】BCH果然最强
  4. Openstack Tempest测试入门
  5. Cookie中不能有空格_PHP 使用cookie
  6. 与TIME_WAIT相关的几个内核参数
  7. Blockchain.com,Eden Block,DACM等知名公司加入Pocket生态
  8. linux(Centos7系统)中安装JDK、Tomcat、Mysql
  9. Java集合高频面试题(最新版)
  10. 2015计算机二级office真题,2015年计算机二级office题库及答案
  11. Zabbix安装配置详解
  12. 飞秋2013官方下载
  13. 随笔(一)—2018-1-23-ANU暑期学校-无题
  14. JS JQuery实现简单的鼠标移动动画效果
  15. 无位置传感器的电机控制
  16. 立根铸魂 崛起数智时代 欧拉部署超300万套
  17. 【Pytorch】区分detach()和torch.no_grad()
  18. python小项目之淘宝秒杀
  19. Spring注解的作用
  20. 【POJ 2987】Firing

热门文章

  1. Web前端 | HTML | 基础
  2. The APR based Apache Tomcat Native library which allows optimal performance in production environmen
  3. 高斯帕滑翔机枪matlab,高斯帕滑翔机枪的播种机这么做?
  4. 《中国睡眠研究报告2022》:被调查大学生睡前不看手机的不足3%
  5. virtualbox复制vdi
  6. Java小游戏之《大鱼吃小鱼》
  7. 图片:“给你五十行代码把我变成字符画!” 程序:“太多了,一半都用不完!”
  8. 洛谷 4238 【模板】多项式求逆
  9. 赛码网刷题python
  10. 2022-03-25 redis组建哨兵及主从高可用的failover