原文链接:http://www.studyshare.cn/blog-front/blog/details/1132

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

 

二、解决方案

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

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

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

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

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

核心思想如图:

 

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

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

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

2.1、SpringBoot框架下代码实现

延时队列实体Bean

 

 

延时订单业务处理接口

 

延时订单业务处理实现类

 

 

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

 

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

2.2、JFinal框架下代码实现

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

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

(2)延时订单业务接口

 

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

 

不是使用spring的注解,这两个方法在JFinal框架下怎么调用,见下图

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

 

该类有两个方法:

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

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

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

 

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

 

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

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

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

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

实现步骤:

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

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

(1)、接口实现类

 

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

 

 

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

 

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

更多深度技术好文:http://www.studyshare.cn/blog-front//index

限时订单实现方案(DelayQueue、ActiveMq)的更多相关文章

  1. Dubbo学习系列之七(分布式订单ID方案)

    既然选择,就注定风雨兼程! 开始吧! 准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7.13/Mysql8.0.11/Lombok0.26/Erl ...

  2. 并发容器之阻塞队列DelayQueue的使用案例及源码分析

    原文连接:(http://www.studyshare.cn/blog-front//blog/details/1167/0 ) 一.队列及阻塞队列概念 1.队列:是一种特殊线性表,特殊之处在于操作是 ...

  3. ActiveMQ基础教程----简单介绍与基础使用

    概述 ActiveMQ是由Apache出品的,一款最流行的,能力强劲的开源消息总线.ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,它非常快速,支持多 ...

  4. RabbitMQ实现订单超时案例

    前言 人间清醒 目录 前言 业务场景 JUC(DelayQueue)方案 DelayQueue简介 JUC DelayQueue实现订单超时案例代码 案例代码 Redis Key过期事件方案 简介 R ...

  5. 快递查询api(多接口方案)

    /** 本环境使用php+smarty,结合两种快递api调取快递数据 * 说明,先快递鸟调取数据,失败后再调取快递网的数据* 快递鸟 http://www.kdniao.com 快递网 http:/ ...

  6. 关于ActiveMQ的一点总结

    ActiveMQ入门 作者:一路向北 摘要:本文主要讲述ActiveMQ的基本知识和使用方法,并简单结合spring使用ActiveMQ. 一.ActiveMQ特性和使用总览 企业消息软件从80年代起 ...

  7. ActiveMQ in Action(6) - Features

    关键字: activemq 2.6 Features    ActiveMQ包含了很多功能强大的特性,下面简要介绍其中的几个.2.6.1 Exclusive Consumer    Queue中的消息 ...

  8. ActiveMQ入门介绍

    1.JMS简介 JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到实际的业务需 ...

  9. ActiveMQ消息持久化存储策略

    ActiveMQ的内核是Java编写的,也就是说如果服务端没有Java运行环境ActiveMQ是无法运行的.ActiveMQ启动时,启动脚本使用wrapper包装器来启动JVM.JVM相关的配置信息在 ...

随机推荐

  1. centos7进单用户

    当重启linux系统,进入系统选择页面的时候,按e 在linux16那一行最后面添加 init=/bin/sh 按ctrl+c 挂载根分区,可读写 mount / -o rw, remount

  2. 2017第八届蓝桥杯C/C++语言A组

    一:题目: 标题:迷宫 X星球的一处迷宫游乐场建在某个小山坡上.它是由10x10相互连通的小房间组成的. 房间的地板上写着一个很大的字母.我们假设玩家是面朝上坡的方向站立,则:L表示走到左边的房间,R ...

  3. 常用的几个CSS前端效果

    做页面需要一定的CSS基本功,虽然现在有很多成熟的框架如bootstrap等,我们轻松的就就可以做出一些页面效果.但是掌握每一个常见效果的写法还是很重要的,下面整理出一些常见的CSS前端效果,让你更轻 ...

  4. 创建一个dynamics 365 CRM online plugin (六) - Delete plugin from CRM

    我们之前都学习到怎么添加,debug还有update plugin. 今天带大家过一下怎么从CRM instance当中删除plugin. 首先让我们打开Settings -> Customiz ...

  5. oracle 中update多个字段

    update  A set (A.a2,A.a3) =(select B.b2,b.b3 from  B where B.b1= A.a1 and A.a3=100 )

  6. java中super关键字的作用

    1.super关键字可以在子类的构造方法中显示地调用父类的构造方法,super()必须为子类构造函数中的第一行. 2.super可以用来访问父类的成员方法或变量,当子类成员变量或方法与父类有相同的名字 ...

  7. siftflow-fcn32s训练及预测

    一.说明 SIFT Flow 是一个标注的语义分割的数据集,有两个label,一个是语义分类(33类),另一个是场景标签(3类). Semantic and geometric segmentatio ...

  8. 【mysql】字段类型和长度的解释

    int(11)最大长度是多少,MySQL中varchar最大长度是多少? int(11)最大长度是多少? 在SQL语句中int代表你要创建字段的类型,int代表整型,11代表字段的长度. 这个11代表 ...

  9. window7 修改docker安装的machine 位置

    win7下安装docker ,默认的machine location 是在C:\users\xx\.docker\machine\machines 下面,为了不占用系统盘,想修改盘符位置 google ...

  10. 20175227张雪莹 2018-2019-2 《Java程序设计》第八周学习总结

    20175227张雪莹 2018-2019-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章 泛型与集合框架 泛型:主要目的是可以建立具有类型安全的集合框架,如链表.散列 ...