rabbitmq延时队列自动解锁库存

一、库存服务自动解锁库存

在这里插入图片描述

使用了最终一致性来解决分布式事务
当order服务出现异常回滚,此时ware服务无法回滚,怎么办?

使用seata全局事务虽然能在order服务出现异常导致回滚时使其他服务的也能同时回滚,但在流量大的情况下是使用加锁的方式,效率
低不适合并发量大的情况,也可以使用定时任务轮询去查看订单的状态,但是轮询的方式比较占资源和内存,所以选用最终一致性的方案,使用mq延时队列死信路由,然后做出补救方案,只要订单服务出现故障就通过mq定时去判断,只要能保证库存最终能解锁即可

延时队列自动解锁库存业务逻辑
ware服务在完成锁库存时就给mq发消息,把消息存到死信队列中,这个消息记录了那些商品锁定多少库存,当queue到达存活时间就会把消息交给死信路由交换机,死信路由交换机会把消息发到最终的队列,如果订单支付时间为30分钟,我们就把存活时间设置为40分钟,这样就能保证我们监听的消息一定是超过了支付的时间的,然后让ware库存服务去订阅监听最终的队列即可,只要有消息我们就去检验order订单服务,只要证明订单服务出现异常回滚或者订单超过支付时间未支付的订单我们就去做一个解锁还原库存的操作

1.库存锁定成功,给mq发消息

(1)保存 工作单(订单号)、工作单详情(商品锁了多少库存)
(2)把上面的数据给mq发一份

@Transactional@Overridepublic boolean orderStock(OrderStockRequest orderStockRequest) {//保存工作单WareOrderTaskEntity wareOrderTaskEntity = new WareOrderTaskEntity();wareOrderTaskEntity.setOrderSn(orderStockRequest.getOrderSn());wareOrderTaskService.save(wareOrderTaskEntity);List<OrderItemVo> itemVos = orderStockRequest.getItemVos();List<SkuStockfromWare> collect = itemVos.stream().map(item -> {SkuStockfromWare skuStockfromWare = new SkuStockfromWare();skuStockfromWare.setSkuId(item.getSkuId());skuStockfromWare.setNum(item.getCount());//查询该商品在那些仓库有库存List<Long> wareId = wareSkuDao.skuStockfromWare(item.getSkuId());skuStockfromWare.setWareId(wareId);return skuStockfromWare;}).collect(Collectors.toList());//根据skuId遍历for (SkuStockfromWare skuStockfromWare : collect) {//判断是否锁定成功boolean flag = false;//判断该商品是否有仓库存在库存List<Long> wareIdList = skuStockfromWare.getWareId();if (wareIdList.size() < 0 || wareIdList == null){throw new NoWareStockException(skuStockfromWare.getSkuId());}for (Long wareId : wareIdList) {Long count = wareSkuDao.LockedStockFromWare(skuStockfromWare.getSkuId(),wareId,skuStockfromWare.getNum());if (count.equals(1L)){//锁定成功flag = true;//保存工作单详情WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();wareOrderTaskDetailEntity.setSkuId(skuStockfromWare.getSkuId());wareOrderTaskDetailEntity.setSkuNum(skuStockfromWare.getNum());wareOrderTaskDetailEntity.setTaskId(wareOrderTaskEntity.getId());wareOrderTaskDetailEntity.setWareId(wareId);wareOrderTaskDetailEntity.setLockStatus(1);wareOrderTaskDetailService.save(wareOrderTaskDetailEntity);//TODO 库存锁定成功->发消息给交换机StockLocked stockLocked = new StockLocked();stockLocked.setTaskId(wareOrderTaskEntity.getId());WareOrderTaskDetailTo wareOrderTaskDetailTo = new WareOrderTaskDetailTo();BeanUtils.copyProperties(wareOrderTaskDetailEntity,wareOrderTaskDetailTo);stockLocked.setDetailTo(wareOrderTaskDetailTo);//convertAndSend(String exchange, String routingKey, Object object)rabbitTemplate.convertAndSend("stock-event-exchange","stock.locked",);//该商品锁定库存成功就执行下一个商品break;}}//如果没有一个仓库扣成功,代表此skuId的库存不足if (!flag){throw new SkuNoStockException(skuStockfromWare.getSkuId());}}return true;}

2.监听队列,解锁库存

(1)判断工作单是否存在
不存在代表锁库存操作已回滚,不做处理
(2)查询订单是否存在
如果订单不存在,表示下订单操作已回滚,执行解锁库存操作
如果存在,查询订单状态是否为 4-已关闭,如果是 4-已关闭,执行解锁库存操作,订单其他状态不做处理
(3)解锁前判断工作单的状态是否为 1-已锁定,证明只做了锁定库存操作
(4)解锁库存,修改工作单详情状态为 已解锁

/*** 解锁库存*/
@RabbitListener(queues = {"stock.release.stock.queue"})
@Service
public class UnLockStockListener {@AutowiredWareSkuService wareSkuService;@RabbitHandlerpublic void UnLockStock(StockLockedTo lockedTo, Channel channel, Message message) throws IOException {try {wareSkuService.unlockStock(lockedTo);//签收channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);} catch (Exception e) {//拒签,让消息重新归队,等待服务器重启进行下一次解锁channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);}}}

解锁操作

/*** 解锁库存** (1).判断工作单是否存在*      不存在代表已回滚,不做处理*      (2).查询订单是否存在*          如果订单不存在,表示已回滚*             (3).执行解锁库存操作*          如果存在,查询订单状态是否为 4-已关闭*                如果是 4-已关闭,执行解锁库存操作,订单其他状态不做处理*/@Overridepublic void unlockStock(StockLockedTo lockedTo) {WareOrderTaskEntity taskEntity = wareOrderTaskService.getById(lockedTo.getTaskId());//已回滚不做处理if (taskEntity != null){//查询订单是否存在R<OrderVo> r = orderFeignService.orderStatus(taskEntity.getOrderSn());if (r.getCode() == 0){OrderVo orderVo = r.getData(new TypeReference<OrderVo>() {});if (orderVo == null || orderVo.getStatus() == 4){WareOrderTaskDetailTo detailTo = lockedTo.getDetailTo();//判断工作单的状态是否为 1-已锁定,证明只做了锁定库存操作if (detailTo.getLockStatus() == 1){//恢复库存unlock(detailTo.getId(),detailTo.getSkuNum(),detailTo.getSkuId(),detailTo.getWareId());}}}else {throw new OrderFeignException();}}}/*** 解锁库存* UPDATE `wms_ware_sku` SET stock_locked = stock_locked - ?* WHERE sku_id = ? AND ware_id = ?*/private void unlock(Long id,Integer skuNum, Long skuId, Long wareId) {wareSkuDao.unlock(skuNum,skuId,wareId);//修改状态为 已解锁WareOrderTaskDetailEntity wareOrderTaskDetailEntity = new WareOrderTaskDetailEntity();wareOrderTaskDetailEntity.setId(id);wareOrderTaskDetailEntity.setLockStatus(2);}

二、订单服务关闭订单同时也执行解锁库存操作

在这里插入图片描述

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

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

相关文章

k8s服务发现之第二弹Service详解

创建 Service Kubernetes Servies 是一个 RESTFul 接口对象&#xff0c;可通过 yaml 文件创建。 例如&#xff0c;假设您有一组 Pod&#xff1a; 每个 Pod 都监听 9376 TCP 端口每个 Pod 都有标签 appMyApp apiVersion: v1 kind: Service metadata:name: my-service spec:s…

vue3笔记-脚手架篇

第一章 基础篇 第二章 脚手架篇 vue2与vue3的一些区别 响应式系统&#xff1a; Vue 2 使用 Object.defineProperty 进行响应式数据的劫持和监听&#xff0c;它对数据监听是一项项的进行监听&#xff0c;因此&#xff0c;当新增属性发生变化时&#xff0c;它无法监测到&…

ASP.NET Website 项目 .NET Framework 4.0 ~ .NET Framework 4.8支持c#哪些版本(Website)

本文讲的是Website网站项目&#xff0c;由于维护老项目Website .net framework4.0&#xff0c;遇到c#6.0语法不支持。便做了点记录 ASP.NET Website 项目 .NET Framework 4.0、 .NET Framework 4.5、 .NET Framework 4.6、 .NET Framework 4.8都支持c#哪些版本&#xff1f; 下面…

MongoDB源码安装

文章目录 MongoDB源码安装&#xff1a;注&#xff1a;下载&#xff1a;解压&#xff1a;创建数据目录&#xff1a;创建软链接&#xff1a;创建变量脚本&#xff1a;执行脚本&#xff1a;启动mongodb:检查&#xff1a;连接mongodb&#xff1a; MongoDB源码安装&#xff1a; 注&…

react+unittest+flask 接口自动化测试平台

目录 1 前言 2 框架 2-1 框架简介 2-2 框架介绍 2-3 框架结构 3 平台 3-1 平台组件图 1 新建用例 2 生成测试任务 3 执行并查看测试报告 3-2 用例管理 3-2-1 用例设计 3-3 任务管理 3-3-1 创建任务 3-3-2 执行任务 3-3-3 测试报告 3-3-4 邮件通知 1 前言 在现…

jar程序部署的外部依赖和按名传参和shellUtil传参json串及返回pid问题

文章目录 指定jar程序运行的外部依赖指定参数名称传参给程序shellUtil命令传参JSON串shellUtil获取回调nohub启动程序后的pid 指定jar程序运行的外部依赖 nohup java -Djava.ext.dirs./lib/ -cp DataSourceAccessPage.jar com.sitech.adapter.JsonAdapter arg0 arg1java -cp 命…

数学建模常用模型(九) :偏最小二乘回归分析

数学建模常用模型&#xff08;九&#xff09; &#xff1a;偏最小二乘回归分析 偏最小二乘回归&#xff08;Partial Least Squares Regression&#xff0c;PLS Regression&#xff09;是一种常用的统计建模方法&#xff0c;用于解决多元线性回归中自变量间高度相关的问题。在偏…

Http 接口测试框架

目录 前言&#xff1a; 实际效果 框架的下一步 最新框架图&#xff08;红色部分未完成&#xff09; 部分代码 你需要做的 前言&#xff1a; 在进行HTTP接口测试时&#xff0c;使用一个可靠的测试框架可以提高测试效率和质量。HTTP接口测试框架是一种用于自动化测试HTTP接…

vue 通过多组复选框来过滤数据

1.通过if else 来筛选数据 <template> <div><div><label><input type"checkbox" v-model"checkedNames" value"北京"> 北京</label><label><input type"checkbox" v-model"chec…

ubuntu 20.04 4090 显卡驱动安装 深度学习环境配置

1. 显卡驱动安装 准备工作&#xff1a; 换源安装输入法&#xff1a;重启的步骤先不管&#xff08;自选&#xff09;sudo apt update && sudo apt upgrade 禁用nouveau驱动&#xff08;这个驱动是ubuntu开源小组逆向破解NVIDIA的开源驱动&#xff0c;与英伟达的原有驱…

Flask_使用flask_marshmallow序列化数据

代码如下&#xff1a; from flask import Flask from flask_marshmallow import Marshmallow from flask_sqlalchemy import SQLAlchemy from marshmallow import fieldsapp Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] "mysqlpymysql://root:12…

Apikit 自学日记:私有云才有的测试文件库功能,该如何使用呢

在 APIkit 的私有云版本中&#xff0c;提供了测试文件库功能。不过目前该功能仅供私有云产品&#xff0c;线上SaaS产品不提供测试文件库功能 API自动化测试中可以添加文件参数。在这里统一管理所有测试文件。 在测试文件库界面&#xff0c;点击上传文件&#xff1a; 在私有云产…

opencv -12 图像运算之按 《位或》 运算(图像融合图像修复和去除)

位或运算 或运算的规则是&#xff0c;当参与或运算的两个逻辑值中有一个为真时&#xff0c;结果就为真。其逻辑关系可以类比为如图 所示的并联电路&#xff0c;两个开关中只要有任意一个闭合时&#xff0c;灯就会亮。 3-5 对参与或运算的算子的不同情况进行了说明&#xff0c;…

Linux操作系统升级低版本的OpenSSH到9.3的高版本

OpenSSH 9.3之前的版本存在各种各样的安全漏洞&#xff0c;为此&#xff0c;我们需要将OpenSSH升级到最新的9.3的版本。 执行&#xff1a;ssh -V&#xff0c;我们可以查看当前的openssh版本 为了避免升级过程中出现意外而导致服务器无法正常使用&#xff0c;建议操作前先对服务…

力扣 406. 根据身高重建队列

题目来源&#xff1a;https://leetcode.cn/problems/queue-reconstruction-by-height/description/ C题解1&#xff1a;分别对h和k两个维度进行考虑&#xff0c;我这里是优先考虑k值&#xff0c;k值相同的时候h小的排前面。然后再一一遍历&#xff0c;对于people[i]&#xff0c…

Nacos报错Could not resolve placeholder ‘order.name‘ in value “${order.name}“怎么解决?

出现这个原因有两个&#xff1a; 1.首先在Nacos配置中心&#xff0c;写入yml配置文件的数据和后端服务在取数据的时候名称不一致 如下图&#xff0c;现在我的配置中心为order-service 看看其中的文件内容信息&#xff1a; 再看看后端是怎么取的&#xff1a; 看出上面错误了吗…

西安---高时空分辨率、高精度一体化预测技术之风、光、水能源自动化预测技术应用

能源是国民经济发展和人民生活必须的重要物质基础。在过去的200多年里&#xff0c;建立在煤炭、石油、天然气等化石燃料基础上的能源体系极大的推动了人类社会的发展。但是人类在使用化石燃料的同时&#xff0c;也带来了严重的环境污染和生态系统破坏。近年来&#xff0c;世界各…

vue写车牌号 自定义键盘

vue写车牌号自定义键盘 <template><div><div class"content-wrapper"><div class"content-top-wrapper"><van-radio-group v-model"radioCarType"><van-radio name"1">蓝牌<imgslot"icon…

什么是渲染?一文看懂,萌新赶紧收藏码住!

十四五规划提出“加快数字化发展&#xff0c;建设数字中国”&#xff0c;数字技术的快速发展&#xff0c;从起初的内容创建到最终的效果呈现&#xff0c;都离不开渲染技术。目前&#xff0c;渲染技术被广泛应用于教育、医疗、影视动画、建筑设计等多个领域。它能有效满足用户对…

Java版企业工程项目管理系统源码+java版本+项目模块功能清单+spring cloud +spring boot

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…