订单提交后30分钟未付款,如何自动取消订单功能实现?

2026-04-02 02:271阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1787个文字,预计阅读时间需要8分钟。

订单提交后30分钟未付款,如何自动取消订单功能实现?

摘要:用户提交订单,30分钟未付款,取消订单功能分析。业务需求为在一段时间之后,完成一个工作任务。实现此类定时任务有哪些方法?总结以下方法。

方法一:使用数据库定时任务

1.在数据库中设置定时任务,如MySQL的EVENT。

2.定时检查订单状态,若超过30分钟未付款,则自动取消订单。

方法二:使用消息队列

1.将订单信息发送到消息队列。

2.消息队列定时处理订单信息,若超过30分钟未付款,则取消订单。

方法三:使用定时任务调度器

1.使用定时任务调度器(如Quartz)。

2.配置定时任务,定时检查订单状态,若超过30分钟未付款,则取消订单。

方法四:使用云服务

1.使用云服务提供的定时任务功能(如阿里云的定时任务)。

2.配置定时任务,定时检查订单状态,若超过30分钟未付款,则取消订单。

总结:

以上四种方法各有优缺点,具体选择哪种方法要根据实际业务需求和资源情况进行判断。以下为总结:

1. 数据库定时任务:简单易用,但性能可能受影响。

2.消息队列:适用于高并发场景,但需要维护消息队列。

3.定时任务调度器:功能强大,但配置较为复杂。

4.云服务:方便快捷,但可能产生额外费用。


摘要

用户提交订单,30分钟还没付款,取消订单功能分析

统一来说,业务有“在一段时间之后,完成一个工作任务”的需求。实现这种定时任务有哪些方法呢,来总结一下想到的方法。

一、定时轮询

这是一个比较直接的思路,启动一个计划任务,每隔一定时间处理一次,这种处理方式只是适用比较小而简单的项目。

假设订单表的结构为:t_order(oid, finish_time, stars, status, …),更具体的,定时任务每隔一个小时会这么做一次:

select oid from t_order where finish_time > 30minite and status=0;
update t_order set stars=5 and status=1 where oid in[…];

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

定时轮询的不足:

  1. 时效性差,会有一定的延迟,这个延迟时间最大就是每隔一定时间的大小,如果你设置每分钟定时轮询一次,那么理论上订单取消时间的最大误差就有一分钟,当然也可能更大,比如一分钟之内有大量数据,但是一分钟没处理完,那么下一分钟的就会顺延。
  2. 效率低。

二、被动取消

被动取消的方式很简单:只有当用户查询订单信息时,我们再判断该订单是否超时,如果超时再进行超时逻辑的处理。但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询订单的操作,该订单就永远不会被取消。

被动取消的不足

  1. 会产生额外影响:比如统计,订单数量等产生影响
  2. 影响用户体验:用户打开订单列表可能要处理大量数据,影响显示的实时性。

三、延时消息

延时消息设计与实现

高效延时消息,包含两个重要的数据结构:

  1. 环形队列,例如可以创建一个包含3600个slot的环形队列(本质是个数组)
  2. 任务集合,环上每一个slot是一个Set

同时,启动一个timer,这个timer每隔1s,在上述环形队列中移动一格,有一个Current Index指针来标识正在检测的slot。
Task结构中有两个很重要的属性:

  1. Cycle-Num:当Current Index第几圈扫描到这个Slot时,执行任务
  2. Task-Function:需要执行的任务指针

假设当前Current Index指向第一格,当有延时消息到达之后,例如希望3610秒之后,触发一个延时消息任务,只需:

  1. 计算这个Task应该放在哪一个slot,现在指向1,3610秒之后,应该是第11格,所以这个Task应该放在第11个slot的Set中
  2. 计算这个Task的Cycle-Num,由于环形队列是3600格(每秒移动一格,正好1小时),这个任务是3610秒后执行,所以应该绕3610/3600=1圈之后再执行,于是Cycle-Num=1

Current Index不停的移动,每秒移动到一个新slot,这个slot中对应的Set,每个Task看Cycle-Num是不是0:

  1. 如果不是0,说明还需要多移动几圈,将Cycle-Num减1
  2. 如果是0,说明马上要执行这个Task了,取出Task-Funciton执行(可以用单独的线程来执行Task),并把这个Task从Set中删除

使用了“延时消息”方案之后,“订单48小时后关闭评价”的需求,只需将在订单关闭时,触发一个48小时之后的延时消息即可:

订单提交后30分钟未付款,如何自动取消订单功能实现?

  1. 无需再轮询全部订单,效率高
  2. 一个订单,任务只执行一次
  3. 时效性好,精确到秒(控制timer移动频率可以控制精度)

订单超时自动取消方案

1、数据库轮询

小型项目常用方式,通过一个线程去扫描数据库或者数据库定时任务,通过订单时间,判断超时的订单,进行更新状态或者其他操作。

2、JDK延迟队列

DelayQueue 是一个无界阻塞队列,只有在延迟期满时才从中获取元素,放入DelayQueue中的对象需要实现Delayed接口。
ProducerDelay生产者生成一个任务 DelayQueue通过poll()或者take()方法获取超时时间任务。然后到达消费者consumerDelay

3、Redis

redis是一个开源的、高性能、基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同的场景,通过提供多种键值数据适应不同场景来适应缓存与存储的需求,value的类型可以提供String Map List Sets sortedSets类型。
redis有序集合 将订单超时的时间戳与订单号分别设置为score与member 系统扫描第一个元素是否超时。

4、MQ

用RabbitMQ ActiveMQ JMS进行判断订单是否超时,队列中可以设置判断类型 从进入队列开始 如果条件符合,直接持久化,如果超过时间将消息删除。


本文共计1787个文字,预计阅读时间需要8分钟。

订单提交后30分钟未付款,如何自动取消订单功能实现?

摘要:用户提交订单,30分钟未付款,取消订单功能分析。业务需求为在一段时间之后,完成一个工作任务。实现此类定时任务有哪些方法?总结以下方法。

方法一:使用数据库定时任务

1.在数据库中设置定时任务,如MySQL的EVENT。

2.定时检查订单状态,若超过30分钟未付款,则自动取消订单。

方法二:使用消息队列

1.将订单信息发送到消息队列。

2.消息队列定时处理订单信息,若超过30分钟未付款,则取消订单。

方法三:使用定时任务调度器

1.使用定时任务调度器(如Quartz)。

2.配置定时任务,定时检查订单状态,若超过30分钟未付款,则取消订单。

方法四:使用云服务

1.使用云服务提供的定时任务功能(如阿里云的定时任务)。

2.配置定时任务,定时检查订单状态,若超过30分钟未付款,则取消订单。

总结:

以上四种方法各有优缺点,具体选择哪种方法要根据实际业务需求和资源情况进行判断。以下为总结:

1. 数据库定时任务:简单易用,但性能可能受影响。

2.消息队列:适用于高并发场景,但需要维护消息队列。

3.定时任务调度器:功能强大,但配置较为复杂。

4.云服务:方便快捷,但可能产生额外费用。


摘要

用户提交订单,30分钟还没付款,取消订单功能分析

统一来说,业务有“在一段时间之后,完成一个工作任务”的需求。实现这种定时任务有哪些方法呢,来总结一下想到的方法。

一、定时轮询

这是一个比较直接的思路,启动一个计划任务,每隔一定时间处理一次,这种处理方式只是适用比较小而简单的项目。

假设订单表的结构为:t_order(oid, finish_time, stars, status, …),更具体的,定时任务每隔一个小时会这么做一次:

select oid from t_order where finish_time > 30minite and status=0;
update t_order set stars=5 and status=1 where oid in[…];

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

定时轮询的不足:

  1. 时效性差,会有一定的延迟,这个延迟时间最大就是每隔一定时间的大小,如果你设置每分钟定时轮询一次,那么理论上订单取消时间的最大误差就有一分钟,当然也可能更大,比如一分钟之内有大量数据,但是一分钟没处理完,那么下一分钟的就会顺延。
  2. 效率低。

二、被动取消

被动取消的方式很简单:只有当用户查询订单信息时,我们再判断该订单是否超时,如果超时再进行超时逻辑的处理。但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询订单的操作,该订单就永远不会被取消。

被动取消的不足

  1. 会产生额外影响:比如统计,订单数量等产生影响
  2. 影响用户体验:用户打开订单列表可能要处理大量数据,影响显示的实时性。

三、延时消息

延时消息设计与实现

高效延时消息,包含两个重要的数据结构:

  1. 环形队列,例如可以创建一个包含3600个slot的环形队列(本质是个数组)
  2. 任务集合,环上每一个slot是一个Set

同时,启动一个timer,这个timer每隔1s,在上述环形队列中移动一格,有一个Current Index指针来标识正在检测的slot。
Task结构中有两个很重要的属性:

  1. Cycle-Num:当Current Index第几圈扫描到这个Slot时,执行任务
  2. Task-Function:需要执行的任务指针

假设当前Current Index指向第一格,当有延时消息到达之后,例如希望3610秒之后,触发一个延时消息任务,只需:

  1. 计算这个Task应该放在哪一个slot,现在指向1,3610秒之后,应该是第11格,所以这个Task应该放在第11个slot的Set中
  2. 计算这个Task的Cycle-Num,由于环形队列是3600格(每秒移动一格,正好1小时),这个任务是3610秒后执行,所以应该绕3610/3600=1圈之后再执行,于是Cycle-Num=1

Current Index不停的移动,每秒移动到一个新slot,这个slot中对应的Set,每个Task看Cycle-Num是不是0:

  1. 如果不是0,说明还需要多移动几圈,将Cycle-Num减1
  2. 如果是0,说明马上要执行这个Task了,取出Task-Funciton执行(可以用单独的线程来执行Task),并把这个Task从Set中删除

使用了“延时消息”方案之后,“订单48小时后关闭评价”的需求,只需将在订单关闭时,触发一个48小时之后的延时消息即可:

订单提交后30分钟未付款,如何自动取消订单功能实现?

  1. 无需再轮询全部订单,效率高
  2. 一个订单,任务只执行一次
  3. 时效性好,精确到秒(控制timer移动频率可以控制精度)

订单超时自动取消方案

1、数据库轮询

小型项目常用方式,通过一个线程去扫描数据库或者数据库定时任务,通过订单时间,判断超时的订单,进行更新状态或者其他操作。

2、JDK延迟队列

DelayQueue 是一个无界阻塞队列,只有在延迟期满时才从中获取元素,放入DelayQueue中的对象需要实现Delayed接口。
ProducerDelay生产者生成一个任务 DelayQueue通过poll()或者take()方法获取超时时间任务。然后到达消费者consumerDelay

3、Redis

redis是一个开源的、高性能、基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同的场景,通过提供多种键值数据适应不同场景来适应缓存与存储的需求,value的类型可以提供String Map List Sets sortedSets类型。
redis有序集合 将订单超时的时间戳与订单号分别设置为score与member 系统扫描第一个元素是否超时。

4、MQ

用RabbitMQ ActiveMQ JMS进行判断订单是否超时,队列中可以设置判断类型 从进入队列开始 如果条件符合,直接持久化,如果超过时间将消息删除。