共计 4012 个字符,预计需要花费 11 分钟才能阅读完成。
简介
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简略易用的分布式事务服务。
Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
角色
Seata 的设计思路是将一个分布式事务能够了解成一个全局事务,上面挂了若干个分支事务,而一个分支事务是一个满足 ACID 的本地事务,因而咱们能够操作分布式事务像操作本地事务一样。
01
三个组件
Seata 外部定义了 3 个模块来解决全局事务和分支事务的关系和处理过程,这三个组件别离是:
Transaction Coordinator (TC):事务协调器,保护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
Transaction Manager (TM):管制全局事务的边界,负责开启一个全局事务,并最终发动全局提交或全局回滚的决定。
Resource Manager (RM):管制分支事务,负责分支注册、状态汇报,并接管事务协调器的指令,驱动分支(本地)事务的提交和回滚。
02
执行步骤
简要说说整个全局事务的执行步骤:
- TM 向 TC 申请开启一个全局事务,TC 创立全局事务后返回全局惟一的 XID,XID 会在全局事务的上下文中流传;
- RM 向 TC 注册分支事务,该分支事务归属于领有雷同 XID 的全局事务;
- TM 向 TC 发动全局提交或回滚;
- TC 调度 XID 下的分支事务实现提交或者回滚。
反对模式
01
Seata AT 模式
两阶段提交协定的演变:
一阶段:业务数据和回滚日志记录在同一个本地事务中提交,开释本地锁和连贯资源。
二阶段:
提交异步化,十分疾速地实现。
回滚通过一阶段的回滚日志进行反向弥补。
02
Seata TCC 模式
整体是两阶段提交的模型。
全局事务是由若干分支事务组成的,分支事务要满足两阶段提交的模型要求,即须要每个分支事务都具备本人的:
一阶段 prepare 行为
二阶段 commit 或 rollback 行为
03
Seata Saga 模式
目前 SEATA 提供的 Saga 模式是基于状态机引擎来实现的,机制是:
- 通过状态图来定义服务调用的流程并生成 json 状态语言定义文件。
- 状态图中一个节点能够是调用一个服务,节点能够配置它的弥补节点。
- 状态图 json 由状态机引擎驱动执行,当出现异常时状态引擎反向执行已胜利节点对应的弥补节点将事务回滚。
- 能够实现服务编排需要,反对单项抉择、并发、子流程、参数转换、参数映射、服务执行状态判断、异样捕捉等性能。
04
Seata XA 模式
利用事务资源(数据库、音讯服务等)对 XA 协定的反对,以 XA 协定的机制来治理分支事务的一种 事务模式。
执行阶段 :
- 可回滚:业务 SQL 操作放在 XA 分支中进行,由资源对 XA 协定的反对来保障 可回滚。
- 长久化:XA 分支实现后,执行 XA prepare,同样,由资源对 XA 协定的反对来保障长久化(即,之后任何意外都不会造成无奈回滚的状况)。
实现阶段 :
- 分支提交:执行 XA 分支的 commit
- 分支回滚:执行 XA 分支的 rollback
源码分享
01
代码整体构造
seata-common
提供一些工具类,异样等。
seata-core
对 rpc,音讯格局,序列化扩大点,eventbus 等做了些封装。
seata-config
配置核心接入,对 naocs,apollo,etcd,zk,file 等做了封装。
seata-discovery
对负载平衡,服务注册发现做了封装,接入 nacos,zk,etcd,eureka 等。
seata-server
coordinator 处理事务协调逻辑
lock 全局锁解决逻辑
store 存储分布式锁
seata-rm
rm 的实现外围逻辑封装。
seata-tm
tm 的外围实现逻辑封装。
seata-tcc
tcc 事务模式扩大。
seata-spring
seata spring 反对,比方 @GlobalLock,@GlobalTransactional 就是在这里反对。
seata-integration
对各种 rpc 反对,比方 xid 透传就在外面实现的。
02
RPC
- AbstractNettyRemoting:Remoting 类的最顶层形象,蕴含了服务端和客户端专用的成员变量与专用办法
- RemotingClient:客户端最顶级接口
- RemotingServer:服务端最顶级接口
- AbstractNettyRemotingClient:客户端抽象类,继承 AbstractNettyRemoting 类并实现了 RemotingClient 接口
- NettyRemotingServer:服务端实现类,继承 AbstractNettyRemoting 类并实现了 RemotingServer 接口
- RmNettyRemotingClient:Rm 客户端实现类,继承 AbstractNettyRemotingClient 类
- TmNettyRemotingClient:Tm 客户端实现类,继承 AbstractNettyRemotingClient 类
- 服务端和客户端启动疏导类
*seata server 与 tm,rm 交互图
针对以上交互图,
seata AbstractNettyRemoting 有一个 processMessage,
外面定义了 processorTable。对于不同申请,采纳不同的 RemotingProcessor 去解决申请逻辑,胜利的将业务逻辑从 netty Netty ChannelHadler 解耦进去。
processor 次要有以下这些。
03
AT 流程
入口 GlobalTransactionScanner, 次要实现 TMClient, RMClient 与 Seata Server 建设连贯。
第一阶段
外围是对业务 sql 进行解析,转换成 undolog,并同时入库。
GlobalTransactionalInterceptor 会对 @GlobalTransactional 注解进行拦挡。
外面会去调用 TransactionalTemplate#execute,进行具体逻辑解决。
次要是有以下几步:
开启全局事务 beginTransaction(txInfo, tx)
执行具体业务逻辑 business.execute()
提交事务 commitTransaction(tx)
如果有异样则进行回滚操作 completeTransactionAfterThrowing(txInfo, tx, ex)
StatementProxy 解析 sql,生成 undolog,执行业务流程,分支事务注册到 seata server 整个流程图。
executeAutoCommitTrue 中先将 autoCommit 设置为 false,起因是要对 sql 进行解析,生成 undolog 在一个事务中入库。
ConnectionProxy#doCommit
如果处于全局事务中,则调用 processGlobalTransactionCommit() 解决全局事务提交。
如果加了全局锁 @GlobalLock 注解,processLocalCommitWithGlobalLocks() 加全局锁并提交。
如果没有任何正文,按间接进行事务提交。
第二阶段
分布式事务操作胜利,则 TC 告诉 RM 异步删除 undolog。
RM 具体解决回调逻辑在 RMHandlerAT。
getResourceManager() 会用到 DataSourceManager,这个是利用 SPI 机制扩大的。
外面是利用 AsyncWorker 异步执行。
解决逻辑次要分以下几步骤:
- 先按 resourceId(数据连贯) 对提交操作进行分组,同个数据库的能够一起操作,晋升效率。
- 依据 resourceId 找到对应 DataSourceProxy,并获取数据库连贯 getPlainConnection()。
- 调用 UndoLogManagerFactory.getUndoLogManager(dataSourceProxy.getDbType()).batchDeleteUndoLog(xids,branchIds, conn) 删除 undolog。
分布式事务操作失败,TM 向 TC 发送回滚申请,RM 收到协调器 TC 发来的回滚申请,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以实现分支的回滚。
具体的实现逻辑在 AbstractUndoLogManager#undo 中能够看到。
解决逻辑次要分以下几步骤:
- 依据 xid,branchId 找到具体的 undolog
- 从 undolog beforeImg 解析回滚 sql 执行
- 删除 undolog,提交
04
其余
TCC 模块扩大了 @TwoPhaseBusinessAction,RMHandlerTCC 等几个点
XA 模块扩大了 DataSourceProxyXA,StatementProxyXA,ConnectionProxyXA 等。
优缺点及总结
- 对于强一致性要求高的场景应用会比拟不便。
- AT 模式会利用 lock_table 锁住具体行,如果分支事务较多,某个分支事务执行较慢,会影响整体性能。
- TCC 模式绝对 AT 模式会可控些,因为 AT 模式回滚镜像是由代码主动生成,也不会有 AT 模式下锁住某一行的问题,然而须要整个链路上下游都进行相应革新,绝对革新老本会较大。
- XA 模式
数据在整个事务处理过程完结前,都被锁定,读写都按隔离级别的定义束缚起来,XA prepare 后,分支事务进入阻塞阶段,收到 XA commit 或 XA rollback 前必须阻塞期待。
性能的损耗次要来自两个方面:一方面,事务协调过程,减少单个事务的 RT;另一方面,并发事务数据的锁抵触,升高吞吐。
- 对 Seata Server 可用性要求很高,一次分布式事务 RM,TM 和 TC 会有屡次交互,对服务稳定性要求也比拟高,1.3 版本后反对了主动降级,然而降级后,强一致性又保障不了了。
- 具体的应用例子可参考:https://github.com/seata/seat…
【END】
文|Leo