12张图带你彻底理解分布式事务产生的场景和解决方案!!

  • 数据隔离的最小单元由RM(资源管理器决定),开发人员无法决定数据隔离的最小单元。比如:数据库中的一条记录等。

ACID属性

说起事务,我们不得不提的就是事务的ACID属性。

在这里插入图片描述

  • A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失

败的情况。

  • C(Consistency):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100元,

转账前和转账后的数据的正确状态叫作一致性,如果出现张三转出100元,李四账户没有增加100元这就出现了数

据错误,就没有达到一致性。

  • I(Isolation):隔离性,数据库中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事

务不能看到其他事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题。

  • D(Durability):持久性,事务完成之后,该事务对数据的更改会被持久化到数据库,且不会被回滚。

分布式事务


随着业务的快速发展,网站系统往往由单体架构逐渐演变为分布式、微服务架构,而对于数据库则由单机数据库架构向分布式数据库架构转变。此时,我们会将一个大的应用系统拆分为多个可以独立部署的应用服务,需要各个服务之间进行远程协作才能完成事务操作。

我们可以使用下图来表示刚开始我们系统的单体架构。

在这里插入图片描述

上图中,我们将同一个项目中的不同模块组织成不同的包来进行管理,所有的程序代码仍然是放在同一个项目中。

后续由于业务的发展,我们将其扩展为分布式、微服务架构。此时,我们将一个大的项目拆分为一个个小的可以独立部署的微服务,每个微服务都有自己的数据库,如下所示。

在这里插入图片描述

又比如,在我们的程序中,经常会在同一个事务中执行类似如下的代码来完成我们的需求。

@Transactional(rollbackFor = Exception.class)

public void submitOrder() {

orderDao.update(); // 更新订单信息

accountService.update(); // 修改资金账户的金额

pointService.update(); // 修改积分

accountingService.insert(); // 插入交易流水

merchantNotifyService.notify(); // 通知支付结果

}

上述代码中的业务,仅仅在submitOrder()方法上添加了一个@Transactional注解,这能够在分布式场景下避免分布式事务的问题吗?很显然是不行的。

如果上述代码所对应的:订单信息、资金账户信息、积分信息、交易流水等信息分别存储在不同的数据里,而支付完成后,通知的目标系统的数据同样是存储在不同的数据库中。此时就会产生分布式事务问题。

分布式事务产生的场景


跨JVM进程

当我们将单体项目拆分为分布式、微服务项目之后,各个服务之间通过远程REST或者RPC调用来协同完成业务操作。典型的场景就是:商城系统中的订单微服务和库存微服务,用户在下单时会访问订单微服务,订单微服务在生成订单记录时,会调用库存微服务来扣减库存。各个微服务是部署在不同的JVM进程中的,此时,就会产生因跨JVM进程而导致的分布式事务问题。

在这里插入图片描述

跨数据库实例

单体系统访问多个数据库实例,也就是跨数据源访问时会产生分布式事务。例如,我们的系统中的订单数据库和交易数据库是放在不同的数据库实例中,当用户发起退款时,会同时操作用户的订单数据库和交易数据库,在交易数据库中执行退款操作,在订单数据库中将订单的状态变更为已退款。由于数据分布在不同的数据库实例,需要通过不同的数据库连接会话来操作数据库中的数据,此时,就产生了分布式事务。

在这里插入图片描述

多服务单数据库

多个微服务访问同一个数据库。例如,订单微服务和库存微服务访问同一个数据库也会产生分布式事务,原因是:多个微服务访问同一个数据库,本质上也是通过不同的数据库会话来操作数据库,此时就会产生分布式事务。

在这里插入图片描述

注意:跨数据库实例场景和多服务单数据库场景,本质上都是因为会产生不同的数据库会话来操作数据库中的数据,进而产生分布式事务。这两种场景是大家比较容易忽略的。

分布式事务解决方案


知道了分布式事务产生的场景后,接下来,我们就聊聊分布式事务具体有哪些解决方案。

2PC方案

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit

phase),2是指两个阶段,P是指准备阶段,C是指提交阶段。

这里,我们用MySQL数据库举例,MySQL数据库支持两阶段提交协议,可以分为成功和失败两种情况。

成功情况

在这里插入图片描述

失败情况

在这里插入图片描述

具体流程如下:

准备阶段(Prepare phase): 事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事

务,并写本地的Undo/Redo日志,此时事务没有提交。

(Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数

据文件)

提交阶段(commit phase): 如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者

发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操

作,并释放事务处理过程中使用的锁资源。

使用2PC方案时,需要注意的是:必须在最后阶段释放锁资源。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

img

最后的话

无论是哪家公司,都很重视Spring框架技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!

部分截图:
在这里插入图片描述

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!
面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!**

部分截图:
[外链图片转存中…(img-Cgd9Rbs6-1711532797762)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值