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

本文介绍了四种延时任务处理方案:数据库轮询、JDK延迟队列、Redis有序集合和自定义的环形队列任务调度。这些方法用于解决如订单超时自动取消等场景,提高效率并确保任务精确执行。环形队列方案尤为高效,通过任务集合和循环计数器实现任务的精确定时执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

订单超时自动取消方案


1、数据库轮询

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

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

3、Redis

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

4、延时消息设计与实现

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

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

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

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

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

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

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

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

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

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值