📢📢📢📣📣📣
哈喽!大家好,我是【一心同学】,一位上进心十足的【Java领域博主】!😜😜😜
✨【一心同学】的写作风格:喜欢用【通俗易懂】的文笔去讲解每一个知识点,而不喜欢用【高大上】的官方陈述。
✨【一心同学】博客的领域是【面向后端技术】的学习,未来会持续更新更多的【后端技术】以及【学习心得】。
✨如果有对【后端技术】感兴趣的【小可爱】,欢迎关注【一心同学】💞💞💞
❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️
目录
一、分布式介绍
🌴 什么是分布式?
🌴 分布式的好处?
二、分布式事务
🌴 认识分布式事务
🌴 两将军问题
三、解决方案
🌵 两阶段提交(2PC)
🌵 三阶段提交(3PC)
🌵 Seata
一、分布式介绍
🌴 什么是分布式?
分布式很好理解,核心就是一个字——“拆”,把一个业务拆分成多个子业务,给不同的服务器去处理,这里的服务器可以是单个服务器,也可以是多个服务器集群,一旦处理该业务的服务器出现问题,那么该业务就无法实现了,可以将其理解为一种工作方式。
🌴 分布式的好处?
- 性能扩展:系统负载高,单台机器无法承载,希望通过使用多台机器来提高系统的负载能力。
- 模块化:降低耦合度,提高系统模块的重用度。
- 增强可靠性:如果其中某个节点失效了,则其余的节点可以继续操作,整个系统不会因为一个或少数几个节点的故障而全体崩溃。
二、分布式事务
🌴 认识分布式事务
在分布式场景下,一个系统由多个子系统构成,每一个子系统被称为一个微服务,每个微服务有独立的数据源,以保持独立性。现在有一个电商系统,由购物微服务、库存微服务、订单微服务等组成。
现在用户请求购物微服务下单,那么购物微服务需要做两件事:
第一件事:调用库存微服务扣减相应商品的库存数量。
第二件事:调用订单微服务插入订单记录。
而我们知道一个数据库的本地事务机制只能落到自己身上的CRUD操作上,无法干涉对其他数据库的操作,所以,数据库自身提供的本地事务机制无法确保业务对多数据源全局操作的可靠性,也就是说购物微服务如果第二步操作异常那么该如何保障事务的一致性呢?
故针对多数据源操作提出的分布式事务机制就出现了,分布式事务需要保证这些操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
🌴 两将军问题
两将军问题:有蓝军和白军,一支白军被围困在一个山谷中,山谷的左右两侧是蓝军。困在山谷中的白军人数多于山谷两侧的任意一支蓝军,而少于两支蓝军的之和。若一支蓝军对白军单独发起进攻,则必败无疑;但若两支蓝军同时发起进攻,则可取胜。两只蓝军的总指挥位于山谷左侧,他希望两支蓝军同时发起进攻,这样就要把命令传到山谷右侧的蓝军,以告知发起进攻的具体时间。假设他们只能派遣士兵穿越白军所在的山谷(唯一的通信信道)来传递消息,那么在穿越山谷时,士兵有可能被俘虏。
左侧蓝军派遣出去送信的士兵没有回来,可能是遇到以下两种情况:
(1)命令还没送达就被俘虏了,这时候右侧蓝军根本不知道要何时进攻;
(2)命令送达,但返回途中被俘虏了,这时候右侧蓝军知道要何时进攻,但左侧蓝军不知道右侧蓝军是否知晓进攻时间。
我们把这个两将军问题放到计算机中,现有发送者给接受者发送一个 HTTP请求,然后超时了没有得到响应,主要有以下情况:
1)可能请求由于网络故障根本没有送到服务器,因此写入失败;2)可能服务器收到了,也写入成功了,但是向客户端发送响应前服务器宕机了;
3)可能服务器收到了,也写入成功了,也向客户端发送了响应,但是由于网络故障未送到客户端。
三、解决方案
分布式事务模型介绍:
事务参与者:例如每个数据库就是一个事务参与者。
事务协调者:访问多个数据源的服务程序。
资源管理器(Resource Manager, RM):通常与事务参与者同义。
事务管理器(Transaction Manager, TM):通常与事务协调者同义。
在分布式事务模型中,一个 TM 管理多个 RM,即一个服务程序访问多个数据源;TM 是一个全局事务管理器,协调多方本地事务的进度,使其共同提交或回滚,最终达成一种全局的 ACID 特性。
🌵 两阶段提交(2PC)
2PC 是一种实现分布式事务的简单模型,这两个阶段是:
1)投票阶段:
a、协调者(Coordinator,即事务管理器)会向事务的参与者(Cohort,即本地资源管理器)发起执行操作的 CanCommit 请求,并等待参与者的响应。
b、参与者接收到请求后,会执行请求中的事务操作,记录日志信息(包含事务执行前的镜像),同时锁定当前记录。参与者执行成功,则向协调者发送“Yes”消息,表示同意操作;若不成功,则发送“No”消息,表示终止操作。
c、 当所有的参与者都返回了操作结果(Yes 或 No 消息)后,系统进入了提交阶段。
2)提交阶段:
如果各个参与者回复的都是 yes,则协调者向所有参与者发起事务提交操作,然后所有参与者收到后各自执行本地事务提交操作并向协调者发送 ACK;如果任何一个参与者回复 no 或者超时,则协调者向所有参与者发起事务回滚操作,然后所有参与者收到后各自执行本地事务回滚操作并向协调者发送 ACK。
缺点:
单点故障:一旦协调者出现问题,那么整个第二阶段提交流程将无法运转,更为严重的是,协调者在阶段二中出现问题的话,那么其他的参与者将会处于锁定事务资源的状态中,而无法继续完成事务操作。
数据不一致:在二阶段提交的阶段二中,即提交事务提交的时候,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交,从而导致数据不一致。
🌵 三阶段提交(3PC)
改动1:超时机制
在协调者和参与者中引入超时机制。如果协调者或参与者在规定的时间内没有接收到来自其他节点的响应,就会根据当前的状态选择提交或者终止整个事务。
改动2:准备阶段
在第一阶段和第二阶段中间引入了一个准备阶段,也就是在提交阶段之前,加入了一个预提交阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
🌵 Seata
Seata 为用户提供了 AT、TCC、SAGA 和 XA 事务模式。其中 AT 模式是 Seata 主推的事务模式解决分布式事务问题,Seata有两个设计初衷:
1.对业务无侵入:即减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入
2.高性能:减少分布式事务解决方案所带来的性能消耗
解决分布式事务问题,有两个设计初衷
Seata的AT模式工作流程:
Seata 的 AT 模式建立在关系型数据库的本地事务特性的基础之上,通过数据源代理类拦截并解析数据库执行的 SQL,记录自定义的回滚日志,如需回滚,则重放这些自定义的回滚日志即可。
AT 模式的两个基本阶段是:
1)第一阶段:首先获取本地锁,执行本地事务,业务数据操作和记录回滚日志在同一个本地事务中提交,最后释放本地锁;
基于这样的机制,分支的本地事务便可以在全局事务的第一阶段提交,并马上释放本地事务锁定的资源。
2)第二阶段:如需全局提交,异步删除回滚日志即可,这个过程很快就能完成。如需要回滚,则通过第一阶段的回滚日志进行反向补偿。
小结:
从 AT 模式第一阶段的流程来看,分支的本地事务在第一阶段提交完成之后,就会释放掉本地事务锁定的本地记录。这是 AT 模式和 XA 最大的不同点,在 XA 事务的两阶段提交中,被锁定的记录直到第二阶段结束才会被释放。所以 AT 模式减少了锁记录的时间,从而提高了分布式事务的处理效率。AT 模式之所以能够实现第一阶段完成就释放被锁定的记录,是因为 Seata 在每个服务的数据库中维护了一张 undo_log 表,其中记录了对 t_order / t_repo 进行操作前后记录的镜像数据,即便第二阶段发生异常,只需回放每个服务的 undo_log 中的相应记录即可实现全局回滚。
undo_log 的表结构:
如果这篇【文章】有帮助到你,希望可以给【一心同学】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【后端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【一心同学】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!