本文将会对比 Seata 与 EasyTransaction 两个分布式事务的一些高层设计, 相信大家会有收获.
Seata 的概述
Seata(曾用名 Fescar, 开源版本 GTS)是阿里的开源分布式事务框架, 其 RoadMap 中指出了其希望与社区合作重新构建出一个全面的分布式事务框架.
关于 Seata 的相关介绍可以看这里, 本文不再赘述. 虽然其后续路线有所调整, 但整体适用.
https://github.com/seata/seata/wiki/概览
学习了解 Seata 后我们可以比对着了解 EasyTransaction 的架构设计.
EasyTransaction 概述
EasyTransaction(后简称 ET)的目标也是构建出一个全面分布式事务解决方案, 到目前为止其包含 TCC, 自动补偿(Seata AT), 手动补偿, 可靠事务消息, Saga 事务等等多种形态.
下面将就两个框架在设计上的差异进行分析
核心差异图示
借用 Seata 的一张图:
与 Seata 不同, EasyTransaction 对应的图如下:
TC 差异
Seata:
有独立部署的集中式 TC
RM,TM 与 TC 的交互通过 RPC 进行
TC 中可以看到每个具体的事务分支, 统一协调所有事务分支的提交及回滚
EasyTransaction:
TC 是业务服务进程中的一个模块, 并没有独立出来, 且存在子事务的服务实例都会调用起 TC 模块
如 ServiceA,B,C 都有 TC, 但 ServiceD,E 没有
这里的有无指代的是这一次事务里 TC 的功能有没有被触发
TC 与 TM,RM 的交互在进程内进行
每个 TC 只能协调其直接子事务
如 ServiceA 的 TC 只知道 ServiceB 及 ServiceE 的子事务
但 ServiceB 知道还有 ServiceC 的子事务, 因此可以递归协调
每个服务实例发起的全局事务, 服务实例自身会先尝试一次自协调(大多数都能成功), 若自协调失败, 则由一个服务实例兜底处理事务协调
Seata 有集中式的 TC, 这样其可以 更容易 实现对分布式事务的监管控, 如关于 APM,Metrics, 统一限流 等等功能.
但在 EasyTransaction 中的 TC 形式可以节约 TC 网络交互时间, 在上述 Seata 的业务图中, ET 的形式在两阶段提交中的第一阶段能节约 6 次 网络来回时间 及 正反序列化时间.
[(registerBranch 以及 reportBranch)* n 个调用层级]
在两阶段提交的第二阶段中, 统一提交或者回滚过程中, Seata 的形式则是比 EasyTransaction 快, 因为其不需要层级传递下去. 视调用层级 N 的区别, ET 形态的第二阶段会比 Seata 慢 n-1 个网络来回及正反序列化的的时间.
[ (commit 或者 rollback) * (n-1)个调用层级]
至于 由于数据分散性等等原因 APM,Metrics, 统一限流 等等功能在 ET 形式如何实现 的这个问题, 我们可以参考普通的 RPC 是怎么做的, 将其纳入统一的 RPC 管理即可, 只是统一管控的力度没有集中式的强大.
同时分散型的 TC 能 更容易 达到更高级别的可用性, 其无需保证 TC 是否存活, 业务服务在则 TC 在. 分散的特征也让压力能在正常业务情况下, 能均匀分散到不同的业务实例当中.
TM 差异
Seata:
独立于 Spring/JTA 的 TransactionManager 单独创建了另外一套 TransactionManager
TransactionManager 在一个全局事务里只有一个
EasyTransaction:
扩展 Spring 的 PlatformTransactionManager(后称 PTM)的功能, 使其可以管控分布式事务
在每个事务分支里都有 PTM(Spring 原生的事务), 但存在子事务的 PTM 将会挂载扩展分布式事务相关处理以及启动 TC 模块功能
Seata 单独抽象了一套 TM, 其好处是自由可控, 并可以不依赖于任何框架.
ET 其 TM 依赖于 Spring 的 PTM 的话, Spring 这个框架就变成了使用 ET 的必选项. 但相对的好处就是, 所有作用于这个 PTM 的设施都可以作用于 EasyTransaction.
例如 Spring 的 RollbackFor,Transactional,Suspend 注解, xml 事务切面配置等等都可以直接为 EasyTransaction 所用. 因为 ET 仅仅只是扩展, 因此这些功能都能兼容. 甚至于我们要引入 JTA,EasyTransaction 也能兼容, 因为 PTM 自身就有 JTA 的实现.
RM 差异
Seata:
所有参与到全局事务的 RM 都是平等的存在
EasyTransaction
存在主控 RM(发起方 RM, 发起方事务), 从事务 RM 的区别
Seata 全局事务里的 RM 都是平等的存在, 整体逻辑上有简单统一的美, 但因此其所有的 RM 都必须能接受两阶段的管控.
但在常规的业务模式中, 全局事务开始者 (Seata 里带 TM 的那个) 的事务, 基本都可以在一阶段内获知全局事务应该回滚或者提交, 但由于 Seata RM 都平等的模式, 发起方 RM 必要要用 AT 模式(记录回滚数据), 或者编写 TCC 的提交回滚方法, 这里有一些额外的性能损耗
ET 模式里存在事务发起方 RM 的设定, 其只要事务发起方的事务提交成功则全局事务 (最终) 提交, 发起方事务提交失败则全局事务 (最终) 回滚, 因此其事务发起方无需兼容两阶段提交的协议, 节约了相关的性能成本.
自动补偿实现差异
Seata:
全局锁通过 TC 保存并实现
EasyTransaction:
全局锁通过本地业务数据库保存
Seata 通过 TC 保存全局记录锁引入了更多的复杂度, 但其能自由控制锁的实现, 能针对场景实现出效率更高的锁.
EasyTransction 改造 Seata 的自动补偿功能, 将原有的远程 TC 依赖改造成了 EasyTransaction 的分布式 TC, 并将全局锁实现改造到业务 DB 中. 自动补偿的整体实现复杂度降低了, 但性能可能有所下降(未经测试).
不过 Seata 相关的实现也在进行中
RPC 接口
Seata
初期 Seata 试图维持其核心功能简洁, 不涉及任何业务层次 RPC 的内容
后面整合蚂蚁的 TCC 后框架核心代码开始出现 RPC 相关内容
暴露给用户的是 RPC 框架原生的接口
接口入参出参形式较为自由
EasyTransaction
RPC 是 EasyTransaction 的一部分, 其可更改替换
直接暴露给用户使用的并非 RPC 框架, 而是 ET 的相关接口, RPC 仅作为底层通讯的支持
接口入参出参形式有限制
EasyTransaction 没有采用常规的做法, 而是用自己的接口替代原 RPC 接口的一个原因是这样做能对整个事务过程能 更容易 地把控, 其直接与业务交互, 知道这一次调用的结果需要马上返回还是可以稍后返回, 知道这一次调用是重试还是业务主动触发的, 可以通过 sdk 主动设置 RPC 框架不进行重试, 主动设置使其进行黏性会话以提高效率而不用用户额外单独配置
同时因为 RPC 是 ET 的一部分, 因此幂等, cancel 悬挂等等繁琐重复的问题, 能更容易地通过框架自动支持(已经实现), 但如果 Seata 坚持目前轻量级做法的话, 将来在实现相关功能时可能会更困难.
当然对业务暴露了 ET 的接口也算是一种耦合的增强.
动态配置, 服务发现, APM 等
Seata
通过主动配置对接
EasyTransaction
利用 Spring 等现有设施对接
ET 利用 Spring 现有的配置接口进行配置, 因此只要相关配置中心对接了 Spring,EasyTransaction 就能使用. 但 Seata 为了减少对 Spring 的依赖, 因此相关对接需要单独进行.
ET 的 TC 整合到业务服务中, 因此 TC 相关的服务发现只要利用业务自身的服务发现就能完成. 而 Seata 的 TC 单独部署, 因此需要一定的适配工作.
跟上面的原因类似, EasyTransaction 的 APM 等操作只需借用已经整合到 RPC 框架的 APM 即可, 而 Seata 需要一定的适配工作
总结
Seata 在短短几个月内能积累近万 Star 除了阿里的技术号召力外, 当然还有另外一个原因是分布式事务领域如此普遍且重要, 但缺少一个能让小白都能放心无脑使用权威的实现, 无疑 Seata 在如此热烈的社区支持下很有希望能成为这么一个实现.
但在 Seata 真正成为这个权威实现前, 我觉得大家也可以抽空了解下 EasyTransaction 这个目前功能更为强大, 代码更为稳定, 已上过生产的实现~
当然以上内容很多都带个人主观偏见, 希望各位能补充各种看法, 兼听则明!
作者个人公众号
多年金融行业经验, 现为某 Top2 民营银行高级搬砖工, 曾在两家 TOP3 股份制商业银行及一家互金创业公司工作(架构, 核心业务主程),EasyTransaction 作者, 欢迎关注个人公众号, 在这里我会分享日常工作, 生活中对于架构, 编码和业务的思考.
来源: https://www.cnblogs.com/skyesx/p/10674700.html