资讯专栏INFORMATION COLUMN

限时订单实现方案(DelayQueue、ActiveMq)

hosition / 3180人阅读

摘要:一在各种电商网站下订单后会保留一个时间段,时间段内未支付则自动将订单状态设置为已过期。并修改这些数据的状态为已过期。因此以上方式实际开发中基本不予采用。时间到期了才会发送这条消息到消息队列中。

一、在各种电商网站下订单后会保留一个时间段,时间段内未支付则自动将订单状态设置为已过期。(原文链接 )

二、解决方案

1、轮询数据库:实现一个定时器,每隔一段时间去检查一遍数据库里的所有订单,查看其状态是否是未支付并且已经到期。并修改这些数据的状态为已过期。

优点:方法简单,容易实现

缺点:订单状态处理不及时,轮询数据库的次数中可能很多都并没有修改订单(做的无用功),数据库频繁多次被连接浪费数据库资源开销。

因此以上方式实际开发中基本不予采用。开发中真正实现限时订单采用以下两种方案:

2、Java本身的解决方案--DelayQueue,延时队列

核心思想如图:

(1)、用户下单,保存订单到数据库的同时,将该订单以及订单的过期时间推入DelayQueue

(2)、启动一个检查订单到期的线程,该线程使用delayQueue的take()方法获取到期订单,该方法为阻塞方法,如果当前没有到期订单,该方法会一直阻塞等待,直到获取到订单后继续往下执行。

(3)、当take()获取到一个到期订单后,该线程按获取到的订单的id去数据库查询订单并去检查订单状态,如果为未支付,则将状态修改为已过期

java开发工具下载地址及安装教程大全,在这里。
更多深度技术文章,在这里。

2.1、SpringBoot框架下代码实现

延时队列实体Bean

延时订单业务处理接口

延时订单业务处理实现类

如果我们只实现了以上的代码,会存在一个很严重的问题,因为延时订单是存在DelayQueue中的,而DelayQueue是存在内存中的,那么当系 统重启后,DelayQueue中的数据就被清空了,因此当系统重新启动的时候,需要在订单的实现类中去做一个检索数据库订单的操作,将已过期未支付的设置为已过期,将未过期未支付的重新推入DelayQueue队列中。代码如下:

@PostConstruct 注解不重复解释,上面代码中有注释

2.2、JFinal框架下代码实现

由于项目中接口工程使用的是JFinal框架,SpringBoot框架下实现限时订单很简单,而JFinal框架下实现有一点小麻烦,特别在此进行分享

(1)ItemVo类和SpringBoot下的一模一样。不再重复贴代码

(2)延时订单业务接口

(3)延时订单业务处理实现类

首先了解一下,在JFinal框架下会有一个初始化类JFinalConfig,继承该类可以做项目的一些初始化操作

该类有两个方法:

afterJFinalStart() :当JFinal框架初始化完成后执行,仅执行一次

beforeJFinalStop() :当JFinal框架关闭之前执行,仅执行一次

那么我们的延时订单线程初始化与系统重启后检测数据库订单的操作就可以放到afterJFinalStart() 里面进行执行

系统关闭线程中断执行代码:

以上就完整实现了限时订单的功能。

3、ActiveMq消息中间件实现方案

使用DelayQueue方案适合在单台服务器上,如果在分布式环境下,DelayQueue方案则还需要进行改进,存在的问题就是多个服务器会抢夺同一个订单,解决方案就是分区处理,每个服务器只负责自己的订单,不管其他服务器上的订单。

使用DelayQueue的方案在功能上比较好的实现了限时订单的功能,但是可扩展性和伸缩性并不好,那么接下来使用ActiveMq实现,既能实现功能,也能更好的扩展和伸缩(消息中间件的特性就是实现系统的解耦)

实现步骤:

1、用户下单保存到数据库的同时使用消息生产者发送一条消息到ActiveMq消息队列,注意:并不是调用send就马上发送,而是根据过期时间进行延迟发送。时间到期了才会发送这条消息到消息队列中。

2、当消息队列收到该消息的时候,将消息转发给订阅了该队列的消费者,消费者收到消息就去做订单状态检查

(1)、接口实现类

(2)、消息生产者--发送订单到期的消息到消息队列(按过期时间延迟发送)

(3)、消息消费者--修改订单过期状态

以上三个类就是使用ActiveMq消息中间件实现限时订单的所有代码。调用代码很简单就是保存订单的同时将消息发送到消息队列,不在赘述。

原创文章,转载请注明出处。
java开发工具下载地址及安装教程大全,在这里。
更多深度技术文章,在这里。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75963.html

相关文章

  • php+redis实现延迟队列

    摘要:基于有序集实现延迟任务执行,比如某个时间给某个用户发短信,订单过期处理,等等我是在框架上写的,实现起来很简单对于一些不是很复杂的应用足够了,目前在公司项目中使用,后台进程并没有实现多进程,不多说,贴代码,不回排版,见谅命令行脚本执行方法这 基于redis有序集实现延迟任务执行,比如某个时间给某个用户发短信,订单过期处理,等等我是在tp5框架上写的,实现起来很简单,对于一些不是很复杂的应...

    罗志环 评论0 收藏0
  • 如何解决MQ消息消费顺序问题

    摘要:利用的高级特性特性是一种负载均衡的机制。在一个消息被分发到之前,首先检查消息属性。属性为某个值的消息单个消息或消息集合在描述,和的对应关系,以及负载均衡策略时。同样做到了保证消息的顺序情况下,均衡消费的消费消息。 通常mq可以保证先到队列的消息按照顺序分发给消费者消费来保证顺序,但是一个队列有多个消费者消费的时候,那将失去这个保证,因为这些消息被多个线程并发的消费。但是有的时候消息按照...

    Atom 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<