xa是X/Open DTP组织(X/Open DTP group)提出的一种基于两阶段提交协议的分布式事务处理的规范,作为资源管理器(数据库)与事务管理器的接口标准。
资源管理器(resource manager):用来管理系统资源,是通向事务资源的途径。数据库就是一种资源管理器。资源管理还应该具有管理事务提交或回滚的能力。
事务管理器(transaction manager):事务管理器是分布式事务的核心管理者。事务管理器与每个资源管理器(resource manager)进行通信,协调并完成事务的处理。事务的各个分支由唯一命名进行标识
两阶段提交协议(The two-phase commit protocol,2PC)是XA用于在全局事务中协调多个资源的机制。两阶段协议遵循OSI(Open System Interconnection,开放系统互联)/DTP标准,虽然它比标准本身早若干年出现。两阶段提交协议包含了两个阶段:第一阶段(也称准备阶段)和第二阶段(也称提交阶段)。
在分布式事务中,xa事务是通过事务管理器与资源管理器之间的通讯来掌握第一阶段各资源管理器的业务的处理情况,并根据第一阶段的结果通知资源管理器进行第二阶段的commit或者rollback操作,从而达到数据的强一致性。
优点:
1、应用侵入小,不需要在业务中做额外的逻辑处理,对用户无感知
2、基于两阶段提交协议,提供了数据强一致性的保障
缺点:
1、同步阻塞,分两阶段提交,对全局事务资源锁的释放取决于所有资源管理器处理事务的总耗时,并发情况下效率较低,尤其是在对某些公共数据进行频繁修改操作(排它锁独占资源,等到事务被提交才会被释放)
2、单点故障,事务管理器故障会导致整个服务不可用
3、故障情况下导致的数据不一致,提交阶段不允许出错,如若出现网络故障或资源管理器宕机,可能导致数据最终不一致,有的节点事务已提交,而有的节点数据未提交
本地事务:事务控制在同一应用中,应用即是事务管理器,连接着多个资源管理器(数据库)
多节点事务:有单独的事务管理器,事务管理器连接着多个应用,每个应用有单独的资源管理器(数据库)
本地事务 | 多节点事务 | |
---|---|---|
吞吐量 | 单点应用,集中式部署,节省了网络通讯开支,在事务逻辑不复杂的情况下吞吐量较高 | 多节点通讯,多机器部署,在事务逻辑复杂的情况下吞吐量较高 |
可靠性 | 单点应用,故障概率小 | 受节点、网络故障影响较大,可靠性较低 |
扩展性 | 单点应用,架构臃肿,代码耦合,不易维护,重构难度大,扩展性差 | 服务划分清楚,职责明确,代码耦合低,扩展性高 |
应用场景 | 单点应用只适合并发量不高以及对扩展性要求较低的小型应用,不适合复杂业务逻辑的应用 | 适合业务逻辑复杂以及并发量较高的应用 |
tcc是xa的变种,tcc将事务提交分为 Try - Confirm - Cancel 3个操作。
Try:预留业务资源/数据效验
Confirm:确认执行业务操作
Cancel:取消执行业务操作
TCC事务处理流程和 2PC 二阶段提交类似,不过 2PC通常都是在跨库的DB层面,而TCC本质就是一个应用层面的2PC。
平台的txc框架就是基于tcc协议的
xa | tcc | |
---|---|---|
侵入性 | 应用侵入小 | 基于事务补偿机制,应用侵入强 |
吞吐量 | 数据库操作粒度较大,吞吐量较低 | 让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能。 |
数据一致性 | 强一致性 | 最终一致性 |
可靠性 | 提交阶段不允许出错,不受控制,可靠性较低 | 提交阶段允许出错,还有重试机制,可靠性较高 |
应用场景 | 对数据一致性要求较高的应用场景 | 对吞吐量要求较高的应用场景 |
机器环境:2cpu4核,3G内存
数据库:mysql
测试工具:jemter
XA性能测试:
框架:spring-boot+druid+mybatis+atomikos
场景一:模拟单账户转账交易,sql数少于10
1.jemter配置:10线程,循环1000次,样本数10000
测试结果:
2.jemter配置:50线程,循环200次,样本数10000
3.jemter配置:100线程,循环100次,样本数10000
测试结果:
场景二:模拟批量转账交易,100insert,100update语句
1.jemter配置:10线程,循环100次,样本数1000
测试结果:
2.jemter配置:50线程,循环20次,样本数1000
测试结果:
3.jemter配置:100线程,循环10次,样本数1000
测试结果:
TXC性能测试:
框架:spring-boot+druid+mybatis+txc
场景一:模拟单账户转账交易,sql数少于10
1.jemter配置:10线程,循环1000次,样本数10000
测试结果:
2.jemter配置:50线程,循环200次,样本数10000
测试结果:
3.jemter配置:100线程,循环100次,样本数10000
测试结果:
场景二:模拟批量转账交易,100insert,100update语句
1.jemter配置:10线程,循环100次,样本数1000
测试结果:
2.jemter配置:50线程,循环20次,样本数1000
测试结果:
3.jemter配置:100线程,循环10次,样本数1000
测试结果:
性能对比
xa \ tcc | 样本容量 | 平均耗时(ms) | 最小耗时(ms) | 最大耗时(ms) | 吞吐量(个/秒) | |
场景一(单账户转账) | 10线程,循环1000次 | 10000 | 115 \ 42 | 9 \ 20 | 552 \ 207 | 81.4 \ 194.8 |
50线程,循环200次 | 10000 | 465 \ 81 | 7 \ 23 | 1788 \ 299 | 97.1 \ 394.5 | |
100线程,循环100次 | 10000 | 958 \ 138 | 10 \ 24 | 2288 \ 592 | 94.4 \ 428.4 | |
场景二(批量账户转账) | 10线程,循环100次 | 1000 | 1979 \ 982 | 355 \ 243 | 5518 \ 1355 | 4.8 \ 9.4 |
50线程,循环20次 | 1000 | 9696 \ 4943 | 309 \ 284 | 35620 \ 6301 | 4.7 \ 9.0 | |
100线程,循环10次 | 1000 | 19898 \ 9689 | 549 \ 302 | 65840 \ 11850 | 4.5 \ 8.9 |
从性能测试结果来看:
1、txc的总体性能高于xa
2、单账户转账情况下,xa的最小耗时是比txc低的,但是最大耗时远远超过txc,可以看出锁等待耗时较高
3、并发数越高,xa最大耗时和最小耗时差距越大,性能越差,吞吐量变化不大,txc反而吞吐量有显著的上升
4,在插入更新sql数量越多、并发量越大的情况下,xa的性能极不稳定,吞吐量较低