简介
咱们都晓得 Seata
是一个分布式事务的解决方案,明天咱们就来带大家理解一下什么是分布式事务,首先咱们先来理解一下根底的常识——事务,咱们先来理解一下事务的概念是什么。
基本概念
事务四局部形成—— ACID
- A(Atomic):原子性,形成事务的所有操作,要么全副执行胜利,要么全副执行失败,不会呈现局部胜利或者局部失败的状况。
- C(Consistency):一致性,在事务执行前后,数据库的一致性束缚没有被毁坏,比方,小勇去银行取 100 块钱,取之前是 600,取之后应该是 400,取之前和取之后的数据为正确数值为一致性,如果取出 100,而银行外面的钱没有缩小,要么小勇要笑醒了,这个就没有达到一致性的要求。
- I(Isolation): 隔离性,数据库中的事务个别都是并发的,隔离性是只在并发的两个事务执行过程互不烦扰,一个事务在执行过程中不能看到其余事务运行过程的中间状态,通过配置事务隔离级别能够防止脏读,反复读等问题
- D(Durability):持久性,当事务实现之后,事务对数据的更改会被长久化到数据库,且不会回滚
事务分为两局部:本地事务和分布式事务
本地事务:
在计算机系统中,比拟多的是通过关系型数据库来管制事务,这是利用数据库自身的事务个性进行实现的,因为利用次要靠关系型数据库来维持事务,加上数据库和利用都在同一个服务器,所以基于关系型数据的事务又被称为本地事务。
分布式事务:
分布式事务是指事务的参与者、反对事务的服务器、资源服务器以及事务管理者别离位于不同的分布式系统的不同节点之上,且属于不同的利用,分布式事务须要保障这些操作要么全副胜利,要么全副失败,分布式事务就是为了保障在不同服务器上数据库数据的一致性。
Seata 的设计思路是将多个服务器的本地事务组成一个全局事务,上面若干个本地事务,都能满足 ACID,最好造成一个整的分布式事务,操作分布式事务就像是操作本地事务一样。
分布式系统会把一个利用拆分为多个可独立部署的服务,服务于服务之间通常须要近程合作能力实现事务的操作,这种分布式系统环境下因为不同的服务之间通过网络近程合作实现的事务被称为分布式事务,例如供应链零碎中,订单创立(生成订单、扣减库存、履约告诉发货)等
在上图中咱们能够看出,只有波及到操作多个数据源,就会产生事务的问题,咱们在理论开发中应该要防止这这个你问题的呈现,然而尽管零碎的拓展,利用和利用之间必然会产生利用之间事务的拆散,当微服务架构中,次要有 MQ 和 Seata,在理解他们之前,咱们先来理解一下分布式事务是怎么组成,以及如何实现的。
分布式事务
分布式事务是什么?
分布式事务指的是事务的参与者,反对事务的服务器,资源服务器别离位于分布式系统的不同节点之上,通常一个分布式事物中会波及到对多个数据源或业务零碎的操作。
随着互联网的倒退,从之前的繁多我的项目逐步向分布式服务做转换,现如今微服务在各个公司曾经普遍存在,而过后的本地事务曾经无奈满足分布式应用的要求,因而分布式服务之间事务的协调就产生了问题,如果做到多个服务之间事务的操作,可能像本地事务一样遵循 ACID 准则,成为一个难题,然而在大牛们一直的摸索下,终于找到了分布式事务存在两大理论依据:CAP 定律和 BASE 实践
CAP 定律
CAP 定律由一致性 (C)、可用性(A)、分区容错性(P) 组成,在分布式系统中,不可能同时满足Consistency(一致性)/Availability(可用性)/Partition tolerance(分区容错性)
三个个性,最多只能同时满足其中两项。
- 一致性(C):在分布式系统中所有的数据备份,在同一时刻保持一致的个性,所有的利用节点拜访的都是同一份最新的数据正本。
- 可用性(A): 当集群中一部分节点故障当前,集群整体可能响应客户端的读写申请,对数据更新具备高可用性。
- 分区容错性(P): 如果零碎在规定工夫限度内不能达成数据的一致性,就示意要产生分区的状况,以后操作须要在 C 和 A 之间做出抉择,让零碎可能在遇到网络故障等状况的时候,任然可能保障对外提供满足一致性或者可用性的服务。
在上图中咱们能够看到,当咱们用户去购物车外面点击下单结算的时候,首先会通过咱们库存服务,判断库存是否足够,当库存满足,扣减库存当前,咱们须要将数据同步到其余服务器上,这一步是为了保证数据的后果的一致性,这个时候如果网络产生稳定了,咱们的零碎须要保障分区容错性,也就是咱们必须容忍网络所带来的一些问题,此时想保障一致性,就须要舍弃可用性。
然而如果为了保障高可用性,那么在高并发的状况下,是无奈保障在限定工夫内给出响应,因为网络的不牢靠,咱们的订单服务可能无奈拿到最新的数据,然而咱们要给用户做出响应,那么也无奈保障一致性,所以 AP 是无奈保障强一致性的
如果既想要保障高可用又想要保障一致性,必须在网络良好的状况下能力实现,那么解决办法只有一个,那就是须要将库存、订单、履约放到一起,然而这个就下来了咱们微服务的作用,也就不再是分布式系统了
在分布式系统中,分区容错性是必须存在的,咱们只能在一致性和可用性上取舍,在这种条件下就诞生了 BASE 实践
BASE 实践
BASE 由 根本可用 (Basically Available
)、 软状态 (Soft state
) 和 最终一致性 (Eventually consistent
) 三个构建而成,是对 CAP 中一致性和可用性衡量的后果,来源于对互联网零碎分布式实际的总结,是基于 CAP 定理逐渐演变而来的,外围四系那个是及时无奈做到强一致性,然而每个利用都能够依据本身的业务特点,采纳适当的形式来使零碎达到最终一致性。
-
根本可用: 根本可用是指当分布式系统呈现不可预知故障的时候,容许损失局部可用性,然而这里并不是说示意零碎不能够用,次要体现为以下几点:
- 响应工夫上的损失,在失常状况下,一个在线搜索引擎须要在 0.5 秒之内返回给用户响应的查问后果,然而因为呈现故障,查问后果的响应工夫减少了 1 - 2 秒
- 零碎性能上的损失,在失常状况下,一个电子商务网站上进行购物,消费者简直可能顺利的实现每一单操作,然而在一些节日大促销购物高峰期的时候,因为网站上购买量的猛增,为了保证系统的稳定性,局部消费者可能会疏导到一个长期降级解决的页面或者提醒
根本可用的意思是,对于咱们的外围服务是能够应用的,其余的服务能够适当的升高响应工夫,甚至是进行服务降级解决,在以后中,库存和订单必定是外围服务,至于咱们的发货零碎在过后只有保障根本可用就行,它的同步能够慢一点或者提早更高,期待流量顶峰过来当前,在进行复原。
- 软状态: 软状态是指容许零碎中的数据存在中间状态,并认为该中间状态的存在不会影响零碎的整体可用性,即容许零碎不必节点的数据正本之间进行数据同步的过程存在延时
软状态的意思是说,当咱们大量下单的时候,扣减库存时,流量激增,这个时候如果大量拜访到库存或者订单中,可能会将零碎弄垮,这个过程中咱们能够容许数据的同步存在提早,不影响整体零碎的应用。
- 最终一致性: 最终一致性强调的是所有数据正本,在通过一段时间的同步之后,最终都可能达到一个统一的状态,因而,最终一致性的实质是须要零碎保障最终数据可能达到统一,而不是须要实时保证系统的强一致性。
通过流量高峰期当前,通过一段时间的同步,从中间状态最初变成数据最终一致性,保障各个服务数据的一致性。
二阶段提交(2PC)
2PC 即两阶段提交协定,是将整个事务流程分为两个阶段,P 是指筹备阶段,C 是指提交阶段。
就好比咱们去 KCC 买冰淇淋吃,那刚好有流动,第二杯半价,然而你是一个人,这个时候刚好有个小姐姐过去,正在思考买不买冰淇淋吃,这个时候你和她提出了 AA,也就会说只有当你和她都批准买这个的时候,能力购买到,如果两个人中有一个不批准那么就不能买这个冰淇淋吃。
阶段一:筹备阶段 老板要求你先进行付款,你批准付款实现后,再要求女方付款,女方批准付款实现
阶段二:提交阶段 都付款实现,老板出餐,两个人都吃到冰淇淋
这个例子就组成了一个事务。如果男女双方有一个人回绝付款,那么老板就不会出餐,并且会把已收取的钱原路退回。
整个事务过程是由事务管理器和参与者组成的,店老板就是事务管理器,你和那个女孩就是参与者,事务管理器决策整个分布式事务在计算机中关系数据反对两阶段提交协定:
- 筹备阶段(Prepare phase):事务管理器给每个参与者发送
Prepare
音讯,每个数据库参与者在本地执行事务,并写本地的Undo/Redo
日志,此时事务没有提交。
undo
日志是记录批改前的数据,用于数据库回滚
Redo
日志是记录批改后的数据,用于提交事务写入数据文件
- 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时音讯时,间接给每个参与者发送(
Rollback
) 音讯,如果收到参与者都胜利,发送(Commit
) 参与者依据事务管理器的指令执行提交或者回滚操作,并开释事务处理过程中应用的资源。
胜利提交:
事务管理器向所有参与者发送事务内容,询问是否筹备好了,期待参与者的响应,各个参与者事务节点执行事务操作,并将 Undo 和 Redo
信息记入事务日志中。如果参与者胜利执行事务操作,反馈事务管理器 YES 操作,示意事务能够执行,如果协调者从所有的参与者或得反馈都是 Yes 响应,那么就会执行事务提交。
失败:
如果任何一个参与者向事务管理器反馈了 No 指令,或者期待超时之后,事务管理器无奈接管到所有参与者的反馈响应,那么中断事务,发送回滚申请,事务管理器向所有参与者节点发送 RollBack
申请,参与者接管到 RollBack
申请后,会利用在阶段一记录的 Undo 信息执行事务的回滚操作,在实现回滚之后开释事务执行期间占用的资源,参与者在实现事务回滚之后,向协调者发送 ACK 音讯,事务管理器在承受到所有参与者反馈的 ACK 音讯之后,实现事务中断。
三阶段提交(3PC)
3PC 次要是为了解决两阶段提交协定的单点故障问题和放大参与者阻塞范畴。是二阶段提交(2PC)的改良版本,引入参加节点的超时机制之外,3PC 把 2PC 的筹备阶段分成事务询问(该阶段不会阻塞)和事务预提交, 则三个阶段别离为 CanCommit、PreCommit、DoCommit
CanCommit 询问状态
CanCommit
阶段 协调者 (Coordinator
) 会向参与者 (Participant
) 发送CanCommit
音讯,询问是否能够执行操作,参与者收到音讯后,示意可能执行,会返回给协调者可能执行的 (yes) 命令
如果参与者不能执行,会返回 No 命令, 开释资源,完结事务。
PreCommit 预提交
PreCommit
阶段如果协调者收到参与者返回的状态值为 YES,那么就证实它们都有能力去执行这个操作,那么协调者就会向所有参与者 发送 PreCommit
音讯,协调者收到 PreCommit
音讯后,回去执行本地事务,如果执行胜利会将本地事务保留到 undo 和 redo
后,再返回给协调者 YES 指令,如果执行本地事务失败,返回协调者 No, 只有协调者收到一个执行失败,给所有参与者发送中断事务音讯,参与者收到音讯后,对事务进行回滚操作。
在这个阶段参与者和协调者都引入了超时机制,如果参与者没有收到,协调者的音讯,或者协调者没有收到参与者返回的预执行后果状态,在期待超时之后,事务会中断,防止了事务的阻塞。
协调者向参与者发送PreCommit
,如果参与者执行胜利,返回 yes
如果参与者执行失败,只有有一个返回 No 到协调者,协调者会向参与者发送中断事务的音讯,参与者回滚事务。
DoCommit 提交
协调者收到所有参与者返回的状态都是 YES,这时协调者会向所有的参与者都发送 DoCommit
,参与者收到 DoCommit
后,会真正的提交事务,当事务提交胜利后,返回协调者 YES 状态,示意我曾经实现事务的提交了,协调者收到所有参与者都返回 YES 状态后,那么就实现了本次事务。
如果某个参与者返回 No 音讯,协调者发送中断事务音讯(abort),给参与者们,参与者回滚事务
3PC 是 2PC 的升级版,引入了超时机制,解决了单点故障引起的事务阻塞问题,然而 3PC 仍然不能解决事务一致性的问题,因为在 DoCommit 阶段,如果因为网络或者超时等准则导致参与者收不到协调者发送过去的 中断事务音讯(abort),过了这个工夫后,参与者会提交事务,原本是应该进行回滚,提交事务后,会导致数据不统一的问题呈现,2PC 尽管在网络故障状况下存在强一致性被毁坏的问题,然而故障复原当前能保障最终一致性,3PC 尽管有超时工夫,解决了阻塞,进步了可用性,然而就义了一致性,如果针对网络稳定问题导致数据问题这一点上,2PC 是优于 3PC 的
Seata
官网:https://seata.io/zh-cn/docs/overview/what-is-seata.html
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简略易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
在微服务零碎中,个别业务会被拆分成独立的模块,在官网提供的结构图中,咱们能够看到以后次要分为三个模块.
- 库存服务:对于商品库存信息进行减少或者缩小操作
- 订单服务:依据用户指定商品生成订单
- 账户服务:从用户账户中扣除余额,减少积分,保护地址信息等等
在以后架构中,用户筛选心仪的商品下单后,须要三个服务来实现操作,每一个服务的外部都领有一个独立的本地事务来保障以后服务数据的强一致性,然而三个服务组成的全局事务一致性就没方法进行保障,那么 Seata 就是来解决这个问题的。
Seata 术语
官网地址:https://seata.io/zh-cn/docs/overview/terminology.html
在理解 Seata 之前,咱们先来理解一下 Seata 几个要害的概念:
- TC(Transaction Coordinator)事务协调者:
保护全局和分支事务的状态,驱动全局事务提交或者回滚 - TM(Transaction Manager) 事务管理者: 发起者,同时一个 RM 的一种,定义全局事务的范畴,开始全局事务,提交或回滚全局事务。
- RM(Resource Manager) 资源管理器: 参加事务的微服务,治理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚
### Seata 2PC
一阶段: 业务数据和回滚日志记录在同一个本地事务中提交,开释本地锁和连贯资源。
二阶段: 提交异步化,十分疾速地实现。回滚通过一阶段的回滚日志进行反向弥补。
一阶段本地事务提交前,须要确保先拿到 全局锁。拿不到全局锁,不能提交本地事务。
拿全局锁的尝试被限度在肯定范畴内,超出范围将放弃,并回滚本地事务,开释本地锁。
在数据库本地事务隔离级别读已提交或以上的根底上,Seata(AT 模式)的默认全局隔离级别是 读未提交
如果利用在特定场景下,必须要求全局的 读已提交,目前 Seata 的形式是通过 SELECT FOR UPDATE 语句的代理。
Seata 执行流程剖析:
每个 RM 应用 DataSourceProxy
链接数据路,目标是应用 ConnectionProxy
,应用数据源和数据代理的目标是在第一阶段将 undo 和业务数据放在一个本地事务中提交,这样就保留了只有有业务操作就肯定会有 dudo 日志,
在第一阶段中,undo 寄存了数据批改前后批改的值,是为了事务回滚做好筹备,在第一阶段实现就曾经将分支事务提交了,也就开释了锁资源。
TM 开启全局事务开始,将 XID 全局事务 ID 放在事务上下文中,通过 feign 调用将 XID 传入上游服务器中,每个分支事务将本人的 Branch ID 分支事务 ID 和 XID 进行关联,
在第二阶段全局事务提交,TC 会告诉各个分支参与者提交分支事务,在第一阶段曾经提交了分支事务,在这里各参与者只须要删除 undo 即可,并且能够异步执行。
如果某一个分支事务异样了,第二阶段全局事务回滚操作,TC 会告诉各个分支参与者回滚分支事务,通过 XID 和 Branch-ID 找到对应的回滚日志,通过回滚日志生成的反向 SQL 执行,实现分支事务回滚到之前的状态。
Seata 下载安装
下载地址:https://github.com/seata/seata/releases
解压后找到 conf 目录
咱们在启动 seata 之前,首先要启动 nacos,其实也很简略,只须要下载 nacos 后启动就行,不晓得 nacos 怎么操作的看这里的介绍 nacos 根底介绍,启动好之后,咱们再来启动 seata,bin 目录下seata-server.bat
如果咱们看到 8091 端口在监听,并且在 nacos 看到服务注册下来了,就示意咱们 seata 启动胜利了
总结
到这里咱们对于分布式事务的和 seata 的介绍就讲完了,其实对于分布式还有 MQ 实现可靠消息最终一致性,MQ 次要解决了两个性能:本地事务与音讯发送的原子性问题。事务参与方接管音讯的可靠性,下一篇会解说对于 seata 中 AT、TCC、SAGA 和 XA
模式的介绍,感兴趣的小伙伴欢送在下方留言,点赞过百,就是通宵也出下篇。
我是牧小农,怕什么真谛无穷,进一步有进一步的欢喜大家加油!