从0~1实现 单体或微服务下 实现订单未支付超时取消功能 方案(2)-rocketmq 延迟队列方案 完整设计和源码

news2024/9/22 5:29:11
  1. 从0~1实现 单体或微服务下 订单未支付超时取消功能 方案(1)-java delayquene + 注册中心(zookeeper/nacos)高可用方案
  2. 从0~1实现 单体或微服务下 订单未支付超时取消功能 方案(2)-rocketmq 延迟队列方案

场景说明

我们日常接触的电商或者票类平台等都有一些共通的功能,比如下单了,超过某时间未支付,则会自动取消该订单 开发的角度来说就是订单从创建成功状态到取消状态,这个并不能靠前端去维护,一个是安全角度不够,另一个就是性能不足和维护复杂度太高
后台去处理就涉及了同步取消和异步取消两大种类方式,具体如下
说明:本文基于minicloud框架下,各位可以用各自得微服务项目即可,本文主要是提供其中一种思路


常用的实现方案以及优缺点

同步方式-查询时再去同时根绝订单创建时间更取消订单

优点:开发简单
缺点:无法实时,而且比较耗时耗性能,并发性低

异步方式-定时任务轮训取消订单

优点:开发简单,可做高可用
缺点:实时性差,瞬间高并发(比如秒杀)下定时的时间很难做到适中

异步方式-redis key过期通知,需要提前防止一个订单id 对应key以及对应过期时间,过期会触发通知

优点:可以做到实时,复杂度低
缺点:redis 订阅通知不保证一定达到消费端,即使消费端都宕机了也不会重复发送

异步方式-java delayquene

优点: java原生的阻塞队列 delayquene,开发便捷
缺点:内存队列,宕机队列既消失,无法高可用(需配合一些第三方进行高可用,本文是配合nacos注册中心)

异步方式-rocketmq 延时队列

优点:高可用
缺点:但是需要引入mq组件复,杂度增加,开源版仅支持部分固定时间,专业版支持自定义时间

本篇基于rocketmq 延迟队列实现


rocketmq 延迟队列方案介绍

rocketmq 本身支持直接发送延迟消息,发送到broker 后,内部计算时间达到指定时间时才会被消费者可见 开源版只支持固定的时间,发送时用level 一对一等价,规则如下:
1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
对应1~18 这18个level,也就是说1对应1s,2对应5s,3对应10s

rocketmq 延迟队列订单取消流程图

在这里插入图片描述

流程说明

如上图所示,流程很简单
1.请求订单服务下单,下单成功后,发送orderId等信息到延迟队列
2.延迟时间到,消费端接到消息
3.调用订单服务更新订单状态,如果订单为未支付,则变更为取消状态

完整源码

共同部分源码

共通源码参考《单体或微服务下 实现订单未支付超时取消功能 方案(1)-java delayquene + 注册中心(zookeeper/nacos)高可用方案》源码部分

rocketmq 相关发送以及消费端部分源码

发送端代码

在这里插入图片描述

 /**
     * 创建状态为未支付的订单,并发送延迟队列消息
     * */
    @Override
    public void createRandomTimeOrderWithoutPay() {

        //创建订单并插入到数据库
        long orderId = GuidUtil.longGuid();
        OrderEntity testOrder = new OrderEntity();
        testOrder.setOrderId(orderId);
        testOrder.setStatus(1);
        testOrder.setCreateTime(LocalDateTime.now());
        testOrder.setDetail(JSONUtil.toJsonPrettyStr(testOrder));
        orderMapper.insert(testOrder);

        //发送延迟队列
        //clusterServiceInvoker.orderInDelayQuene("core-processer-biz","default",orderId,1);

        //使用发送延迟消息接口发送
        orderWithoutPayQuene.push(orderId,1,TimeUnit.MINUTES);

    }
/**
 * @Author alan.wang
 */
@AllArgsConstructor
@Service("mqOrderWithoutPayQuene")
public class MQOrderWithoutPayQuene implements OrderWithoutPayQuene {

    private final MqMessageSender mqMessageSender;

    @Override
    public void push(long orderId, long expireTime, TimeUnit timeUnit) {

        DelayQueneOrderDTO delayQueneOrderDTO = new DelayQueneOrderDTO();
        delayQueneOrderDTO.setExpireTime(expireTime);
        delayQueneOrderDTO.setOrderId(orderId);
        mqMessageSender.sendOrderWithoutPayInDelayQueneMsg(delayQueneOrderDTO);

    }

    @Override
    public void take() {
       //nothing need to do
    }
}

消费端代码

新建OrderWithoutPayCannelConsumer 消费者,专门处理订单超时未支付延迟队列topic

/**
 * @Author alan.wang
 * 处理订单延迟队列类,将超时未支付的订单状态变为取消
 */
@Slf4j
@Component
@AllArgsConstructor
@RocketMQMessageListener(topic = "topic-order-without-pay", consumerGroup = "test_order_without_pay_group")
public class OrderWithoutPayCannelConsumer implements RocketMQListener<String> {


    @Override
    public void onMessage(String delayQueneOrderJson) {
        
        //获取RemoteSimulateOrderService feign 接口
        RemoteSimulateOrderService remoteSimulateOrderService = SpringContextUtils.getBean(RemoteSimulateOrderService.class);
        
        //转换delayQueneOrderJson
        DelayQueneOrderDTO delayQueneOrderDTO = JSONUtil.toBean(delayQueneOrderJson, DelayQueneOrderDTO.class);
        
        //执行变更订单状态为取消的操作
        remoteSimulateOrderService.updateStatusToCancel(delayQueneOrderDTO.getOrderId());
        System.out.println(delayQueneOrderJson+":"+ LocalDateTime.now());
    }


}

MqMessageSender

 /**
    * 发送订单号等延迟队列消息,10s 后触发消费端可见
    */
    public void sendOrderWithoutPayInDelayQueneMsg(DelayQueneOrderDTO delayQueneOrderDTO) {

        Message<String> msg = MessageBuilder.withPayload(JSONUtil.toJsonStr(delayQueneOrderDTO)).build();

        //30000 代表超时时间,3为level 既:10s
        rocketMQTemplate.syncSend(TOPIC_ORDER_WITHOUT_PAY_DESTINATION,msg,30000,3);
    }

运行并查看结果

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188581.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IronPDF for .NET 2023.1 Crack

关于 .NET 的 IronPDF 创建、编辑和导出 PDF 文档。 IronPDF for .NET 允许开发人员在 C#、F# 和 VB.Net for .NET Core 和 .NET Framework 中轻松创建 PDF 文档。您可以选择简单的 HTML&#xff0c;或合并 CSS、图像和 JavaScript。IronPDF 呈现紧跟谷歌浏览器。 IronPDF 功能…

eclipse新手快捷键

1. ctrlshiftr&#xff1a;打开资源 这组Eclipse快捷键可以让你打开你的工作区中任何一个文件&#xff0c;而你只需要按下文件名或mask名中的前几个字母&#xff0c;比如applic*.xml。美中不足的是这组快捷键并非在所有视图下都能用。 2. ctrlo&#xff1a;快速outline 列出…

2023年深圳Java培训机构排名,不看后悔系列!

不忘初心&#xff0c;方得始终。2023&#xff0c;继续战斗&#xff01;想要学习Java的小伙伴们看过来~深圳Java培训机构排名最新排行榜来了&#xff01;靠谱的Java培训机构都在这里&#xff0c;总有一个你喜欢的&#xff0c;总能选出一个合适你的&#xff0c;快拿出小本本记下这…

【MyBatis】搭建MyBatis

1、MyBatis简介 1.1、MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下&#xff0c; iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github。iBatis一词来源…

2023年flash水坑攻击源码

1. 背景 在有授权的攻防演练中&#xff0c;很多时候都会用到水坑攻击或者钓鱼&#xff0c;目前flash钓鱼一直都在做&#xff0c;以前的版本中&#xff0c;提示flash版本过低是这样的&#xff1a; 下载界面是这样的&#xff08;下图来源于互联网&#xff09;&#xff1a; 但是目…

javascript封装一个单向链表

单向链表 单向链表类似于火车&#xff0c;有一个火车头&#xff0c;火车头会连接一个节点&#xff0c;节点上有乘客&#xff0c;并且这个节点会连接下一个节点&#xff0c;以此类推。 链表的火车结构 链表的数据结构 head 属性指向链表的第一个节点。 链表中的最后一个节点指…

2023年郑州Java培训机构排名新鲜出炉,快来看看都有哪些!

郑州是一个很有发展潜力又极具竞争力的城市&#xff0c;很多大厂现在都在往二线城市转移&#xff0c;其中郑州就是一个很好的选择。所以想要在郑州有好的发展前景&#xff0c;就要不断提高自己的技术竞争力&#xff0c;Java软件开发就成为了不少小伙伴们想要提升价值技能选择的…

Pytorch 基础

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

【职工管理系统】C++全栈体系(十五)

职工管理系统 第十一章 添加职工 功能描述&#xff1a;按照职工的编号进行删除职工操作 一、删除职工函数声明 在workerManager.h中添加成员函数 void Del_Emp(); //删除职工void Del_Emp();二、职工是否存在函数声明 很多功能都需要用到根据职工是否存在来进行操作如&…

基于Android的综合物流系统

需求信息&#xff1a; &#xff08;1&#xff09;后台管理平台 设计实现物流管理平台&#xff0c;完成对司机、所载货物、出发点、目的地、运输轨迹等的管理。主要研究的内容为前后端框架的选择&#xff0c;对系统信息的展示与管理。 数据展示&#xff1a;管理人员通过不同的筛…

Redis持久化 | 黑马Redis高级篇

目录 RDB持久化 1、介绍 2、命令 3、配置 4、bgsave的fork底层原理 5、总结 AOF持久化 1、介绍 2、开启 3、三种写回策略 4、AOF后台重写 混合持久化 总结 Redisd的持久化有两种方式&#xff0c;分别是RDB和AOF RDB持久化 1、介绍 RDB&#xff0c;Redis数据备份…

软件测试项目实战【不爱听书】测试全套教程以及源码

前言 软件测试流程&#xff1a;需求分析—>测试计划—>测试设计—>测试执行—>测试报告 一、需求分析 “不爱听书”是一个为用户提供创作音乐和收听音频的平台。对于该项目的需求分析&#xff0c;提炼出相关测试点。 基本功能需求 用户可以进行注册、登录与退…

使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 下

文章目录1 测试鉴别器2 建立生成器3 测试生成器4 训练生成器5 使用生成器6 内存查看上一节&#xff0c;我们已经建立好了模型所必需的鉴别器类与Dataset类。使用PyTorch构建GAN生成对抗网络源码&#xff08;详细步骤讲解注释版&#xff09;02 人脸识别 上接下来&#xff0c;我们…

Source Insight基本使用

据说阅读Linux源码经常使用此工具&#xff1b;先看一下基本使用&#xff1b; 新建一个工程&#xff1b; OK以后出现下图&#xff1b;这是insight项目的目录&#xff1b; 把要阅读的源码工程加进来&#xff1b; 如下2个选项选中&#xff0c;OK&#xff1b; 如果下图右侧的内容没…

在Windows中操作系统下,检查Python脚本是否已运行

在Windows中操作系统下&#xff0c;检查Python脚本是否已运行 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 一、原理 用一个空的虚拟文件。 在进程开始时&#xff0c;检查文件是…

ruby 给钉钉群发消息

给钉钉群发一条工作消息用途如下: Ipa, apk,打包完成了, 可以用作测试群表格导出成功了, 一般的群消息比如后台日志报警等等 步骤如下 群设置 - 智能群助手 - 添加机器人 - 选择 - 自定义 机器人设置里面要设置一个自定义关键词, 比如这里面 我起个名字 summerxx 上篇说到我…

javaweb高校大学毕业生就业跟踪系统ssm idea maven

系统所要实现的功能分析&#xff0c;对于现在网络方便的管理&#xff0c;系统要实现毕业生可以直接在平台上进行查看所有数据信息&#xff0c;根据需求可以进行在线添加&#xff0c;删除或修改企业信息、问卷调查、问卷提交、招聘信息、投递简历、企业评价、就业调查、就业表提…

(十三)devops持续集成开发——jenkins流水线发布一个sonar qube质量检查项目

前言 在前面的内容中我们已经介绍过如何在jenkins中集成质量检查工具sonar qube&#xff0c;以及sonar qube服务的安装。本节内容我们通过使用jenkins构建一个包含sonar qube质量检查的流水线项目&#xff0c;从而实现项目部署发布上线前的代码质量检查。从而保证系统的稳定性…

带约束进化算法问题分析Constrained Evolutionary Algorithms

经典论文《Evolutionary Algorithms for Constrained Parameter Optimization Problems》对带约束的进化算法进行了综述&#xff0c;本文不涉及其内容的翻译&#xff0c;主要为个人对论文理解和思考。 1. 进化算法定义Evolutionary Algorithms 论文中所讨论的进化算法主要为以…

java泛型5

泛型类 Java泛型不仅允许在使用通配符形参时设定上限&#xff0c;而且可以在定义泛型形参时设定上限&#xff0c;用于表示传给该泛型形参的实际类型要么是该上限类型&#xff0c;要么是该上限类型的子类。 上面程序定义了一个Apple泛型类&#xff0c;该Apple类的泛型形参的上限…