当前位置: 首页 > news >正文

电商项目_核心业务_分布式事务

分布式事务概念

        在微服务架构中,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务。需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。

分布式事务解决方案

2PC

(Two-Phase Commit)

(二阶段提交)

TCC

(Try-Confirm-Cancel)

可靠消息

(MQ)

最大努力通知
一致性强一致性最终一致最终一致最终一致
吞吐量
实现复杂度
具体实现方案

基于 Seata AT 实现

开发者手动实现TCC逻辑RocketMq事务消息三方通知消息重试

2PC

核心角色:协调者、参与者

阶段一:准备阶段(Prepare Phase)
  1. 协调者 向所有参与者发送 Prepare 请求,询问是否可以提交事务。

  2. 参与者 执行本地事务操作(但不提交),记录 Undo/Redo 日志

  3. 参与者 回复协调者:

    • 同意(Yes):本地事务执行成功,已准备好提交。

    • 中止(No):本地事务失败(如违反约束)。

阶段二:提交/回滚阶段(Commit/Rollback Phase)
  • 若所有参与者均回复 "Yes"
    协调者发送 Commit 命令,参与者提交事务并释放锁。

  • 若有任一参与者回复 "No" 或超时
    协调者发送 Rollback 命令,参与者回滚事务(基于日志恢复)

优点
  • 强一致性:所有节点要么全部提交,要么全部回滚。

  • 简单易懂:流程明确,易于实现。

缺点
  • 同步阻塞:参与者需等待协调者指令,期间资源被锁定。

  • 单点故障:协调者宕机会导致事务阻塞(需超时机制补救)。

  • 数据不一致风险

    • 若协调者在发送 Commit 后宕机,部分参与者可能未收到指令(需人工干预)。

    • 网络分区时可能出现部分提交、部分未提交。

TCC

TCC 是一种 柔性事务解决方案,通过业务逻辑拆分为三个阶段(Try、Confirm、Cancel)实现分布式事务的最终一致性。

  1. Try(尝试)

    • 预留资源:检查并锁定资源(如冻结库存、预扣金额)。

    • 若所有参与方 Try 成功,进入 Confirm 阶段;否则进入 Cancel 阶段。

  2. Confirm(确认)

    • 提交业务:基于 Try 阶段的预留资源,完成最终操作(如扣减库存、实际支付)。

    • Confirm 必须保证幂等性(重复调用不产生副作用)。

  3. Cancel(取消)

    • 回滚补偿:释放 Try 阶段预留的资源(如解冻库存、返还预扣金额)。

    • Cancel 也必须保证幂等性。

🔹 关键特点:TCC 是 业务侵入式 的,需要开发者手动实现 Try/Confirm/Cancel 的逻辑。

2PC案例

1. Apache ShardingSphere 分布式事务

        整合 Seata AT 事务时,需要将 TM,RM 和 TC 的模型融入 Apache ShardingSphere 的分布式事务生态中。 在数据库资源上,Seata 通过对接 DataSource 接口,让 JDBC 操作可以同 TC 进行远程通信。 同样,Apache ShardingSphere 也是面向 DataSource 接口,对用户配置的数据源进行聚合。 因此,将 DataSource 封装为 基于 Seata 的 DataSource 后,就可以将 Seata AT 事务融入到 Apache ShardingSphere 的分片生态中。

2. Seata架构

Seata架构中的三个角色:

  1. TC(Transaction Coordinator) 事务协调者: 单独部署的Server服务
  2. TM(Transaction Manager)事务管理器:发起事务的微服务 嵌入TM
  3. RM(Resource Manager)资源管理器:事务参数的微服务嵌入RM

3. 整合Seata实战

1. 微服务引入seta版本依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><version>2.2.8.RELEASE</version><exclusions><exclusion> -- 排除spring-cloud下的seata, 单独引入<groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version>
</dependency>

2. 微服务对应的数据库中 添加undo log表(仅AT模式

(2PC模式下第一阶段记录的日志)

3. 微服务application.yml添加seata配置

注册中心、配置中心

4. 全局事务发起者开启全局事务配置

        订单表使用了分库分表技术(ShardingSphere),seata 不能对逻辑表进行解析。解决方案:

        整合 Seata AT 事务时,需要将 TM,RM 和 TC 的模型融入 Apache ShardingSphere 的分布式事务生态中。 

ShardingSphere整合seata

1)引入依赖

<!--shardingsphere 整合 seata 依赖-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-transaction-base-seata-at</artifactId>
<version>4.1.1</version>
</dependency>

2)配置 seata.conf

3)开启全局事务配置

//全局事务交给 SeataATShardingTransactionManager 管理
@ShardingTransactionType(TransactionType.BASE)
@Transactional
public CommonResult generateOrder(OrderParam orderParam, Long memberId) {

可靠消息案例

就是rocketMq的事务消息保证事务性,之前已经反复分析过多次。

电商系统中典型分布式事务案例

1、用户下单冻结库存

OmsPortalOrderServiceImpl#generateOrder

begin 分布式事务

1. 库存锁定

-- 所谓库存的锁定,库存表是真正的扣减了, 只不过会记录分布式事务日志表,如果需要回滚,根据事务日志表回滚库存信息
<update id="lockStockByExample" parameterType="java.lang.Integer">update pms_sku_stocksetstock = stock - #{lockQuantity,jdbcType=INTEGER},lock_stock = lock_stock + #{lockQuantity,jdbcType=INTEGER}<if test="_parameter != null"><include refid="Update_By_Example_Where_Clause" /></if></update>

一个订单下可能有多个商品,会遍历商品,逐个锁库存。 

2. order表插入记录

3. order_item表插入记录

end 分布式事务

2、支付成功后修改订单状态,异步扣减真实库存

OmsPortalOrderServiceImpl#paySuccess

1. 修改订单表的支付状态(实际情况应该配置个支付记录表)

2. 进行真实库存的扣减,可以使用MQ消息进行异步库存扣减

-- 冻结的值加回去
<update id="updateSkuStock">UPDATE pms_sku_stockSETlock_stock = CASE id<foreach collection="itemList" item="item">WHEN #{item.productSkuId} THEN lock_stock - #{item.changesCount}</foreach>ENDWHEREid IN<foreach collection="itemList" item="item" separator="," open="(" close=")">#{item.productSkuId}</foreach></update>

http://www.xdnf.cn/news/1214479.html

相关文章:

  • 【AI论文】单一领域能否助力其他领域?一项基于数据的、通过强化学习实现多领域推理的研究
  • 少林寺用什么数据库?
  • web:html表单提交数据
  • 亚马逊广告进阶指南:如何合理调配预算
  • 网络的学习 2 Socket
  • 深入剖析 RocketMQ 分布式事务:原理、流程与实践
  • GitPython02-Git使用方式
  • 大模型对比评测:Qwen2.5 VS Gemini 2.0谁更能打?
  • 《C++二叉搜索树原理剖析:从原理到高效实现教学》
  • 基于 Amazon Bedrock 与 Anthropic Claude 3 智能文档处理方案:从扫描件提取到数据入库全流程实践
  • 智能Agent场景实战指南 Day 26:Agent评估与性能优化
  • Python正则表达式精准匹配独立单词技巧
  • 【Dolphinscheduler】docker搭建dolphinscheduler集群并与安全的CDH集成
  • python | numpy小记(八):理解 NumPy 中的 `np.meshgrid`
  • 嵌入式linux驱动开发:什么是Linux驱动?深度解析与实战入门
  • 如何通过IT-Tools与CPolar构建无缝开发通道?
  • OriGene:一种可自进化的虚拟疾病生物学家,实现治疗靶点发现自动化
  • 【ESP32设备通信】-LAN8720与ESP32集成
  • MOEA/DD与MOEA/D的区别
  • 2024 年 NOI 最后一题题解
  • 算法精讲:二分查找(二)—— 变形技巧
  • 【Excel】制作双重饼图
  • 关于windows虚拟机无法联网问题
  • VMware16安装Ubuntu-22.04.X版本(并使用桥接模式实现局域网下使用ssh远程操作Ubuntu系统)
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-51,(知识点:stm32,GPIO基础知识)
  • C++菱形虚拟继承:解开钻石继承的魔咒
  • 简单线性回归模型原理推导(最小二乘法)和案例解析
  • 线性回归的应用
  • 明智运用C++异常规范(Exception Specifications)
  • 爬虫验证码处理:ddddocr 的详细使用(通用验证码识别OCR pypi版)