首页 > 技术文章 > HM-SpringCloud微服务系列9.3.1【实践:XA模式、AT模式】

yppah 2022-04-12 10:46 原文

1. XA模式

1.1 原理

1.1.1 XA模式原理

XA 规范 是 X/Open 组织定义的分布式事务处理(DTP,Distributed Transaction Processing)标准,XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。
image
image

1.1.2 seata的XA模式

seata的XA模式做了一些调整,但大体相似:
image
image

1.1.3 小结

  1. XA模式的优点是什么?
    • 事务的强一致性,满足ACID原则。
    • 常用数据库都支持,实现简单,并且没有代码侵入
  2. XA模式的缺点是什么?
    • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
    • 依赖关系型数据库实现事务

1.2 实现XA模式

第一步修改代码
image
image
image
image
image
第二步重启服务
image
image
第三步测试
image
image
image
正常情况:
image
image
image
image
异常情况:
image
image
image
image
ok钱没被扣
image
image

2. AT模式(seata默认)

2.1 AT模式原理

image
image
image
image
image

2.2 AT模式的脏写问题

image
image
image
image
image
出现丢失更新问题,原因就是事务没有做好隔离,解决如下2.3

2.3 AT模式的写隔离

image


image
image
image
产生死锁:事务1在等待当前属于事务2的DB锁,事务2在等待当前属于事务1的全局锁
image


此处注意避免与XT模式的混淆:XT模式是数据库锁,锁的力度大,一旦锁定,谁都无法访问被锁数据;此处AT的全局锁是事务协调者TC搞得,力度小,他只是记录事务1(有seata管理),若事务2不是由seata管理的,则可以访问数据,例如修改此表中id=1记录的其他字段

image
image
image
image
image
此时,如果事务1直接进行数据恢复将80变为100,则又出现了丢失更新问题
实际上,事务1在保存快照是会保存两份,一份是执行SQL前,一份是之后
image

2.4 实现AT模式

image

注意AT和XA模式一样,也需要在全局事务入口加上@GlobalTransactional注解

lock_table表导入到seata库,用于记录全局锁
undo_log表导入到seata_demo库,用于记录快照信息
image

-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log`  (
  `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
  `xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'global transaction id',
  `context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'undo_log context,such as serialization',
  `rollback_info` longblob NOT NULL COMMENT 'rollback info',
  `log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
  `log_created` datetime(6) NOT NULL COMMENT 'create datetime',
  `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
  UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;

-- ----------------------------
-- Table structure for lock_table
-- ----------------------------
DROP TABLE IF EXISTS `lock_table`;
CREATE TABLE `lock_table`  (
  `row_key` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `xid` varchar(96) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `transaction_id` bigint(20) NULL DEFAULT NULL,
  `branch_id` bigint(20) NOT NULL,
  `resource_id` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `table_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `pk` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gmt_create` datetime NULL DEFAULT NULL,
  `gmt_modified` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`row_key`) USING BTREE,
  INDEX `idx_branch_id`(`branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

image
image
image
image
image
image
image
image
重启三个微服务
image
重启完成,做一下测试
先看一下当前数据
image
image
image
发送请求
image
发现报错500
再来看一下数据库数据有没有恢复
image
image
image
image
ok,数据与原先的一致,说明分布式事务生效,有问题的业务都回滚了
image
image
image
上述undo_log表中没有数据,原因是回滚结束后自动删除了记录,实际上会先插入一条记录再删除

2.5 小结

  1. 简述AT模式与XA模式最大的区别是什么?
    • XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
    • XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
    • XA模式强一致;AT模式最终一致
  2. AT模式的优点:
    • 一阶段完成直接提交事务,释放数据库资源,性能比较好
    • 利用全局锁实现读写隔离
    • 没有代码侵入,框架自动完成回滚和提交
  3. AT模式的缺点:
    • 两阶段之间属于软状态,属于最终一致
    • 框架的快照功能会影响性能,但比XA模式要好很多

推荐阅读