05-AT模式

AT模式同样是分阶段提交事务的模型,不过弥补了XA模式锁定资源周期长的问题。

1.seata的AT的模型

基本流程图:

 阶段一RM的工作:

  注册分支事务;

  记录undo-log(数据快照);

  执行业务sql并且提交;

  报告事务状态;

阶段二提交RM的工作:

  删除undo-log即可

阶段二回滚RM的工作:

  根据undo-log回复数据到更新前;

2.流程梳理

用一个真是的业务场景梳理AT模式的原理。

比如现在有一个数据库表,记录账户余额:

 其中一个分支业务要执行业务sql:

update tb_account set money = money - 10 where id = 1

AT模式下,当前分支事务执行流程如下:

 一阶段:

  1)RM发起并注册全局事务到TC

  2)RM调佣分支事务

  3)分支事务准备执行业务SQL

  4)RM拦截拦截业务SQL,根绝where条件,形成快照。

  

{
    "user202103032042012": 1, "money": 100
}

  5)RM执行业务SQL,提交本地事务,并释放数据库锁,此时,money=90

  6)RM报告事务状态给TC

 二阶段:

  1)TM通知TC事务结束

  2)TC检查事务状态:

    a)如果都成功,则立即删除快照。

    b)如果有分支事务失败,则需要回滚,根据快照恢复数据。

流程图:

  

 3.XA和AT的区别

  1)XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。

  2)XA模式依赖数据库机制实现回滚;AT模式使用数据快照实现回滚。

  3)XA是强一致,AT是最终一致。

4.脏写问题

在多线程并发访问AT模式的分布式事务,会出现脏写问题,如图:

 

解决思路是引入全局锁。在释放DB锁之前拿到分布式锁。避免同一时刻有另一个事务操作当前数据。

 

5.优缺点

  AT模式优点:

    1)一阶段完成直接事务提交,释放数据库资源,性能比较好。

    2)利用全局锁实现读写隔离

    3)没有代码进入,代码自动完成回滚和提交。

  AT模式缺点:

    1)两阶段之间属于软状态,是最终一致。

    2)框架的快照功能会影响性能,但是比XA模式好很多。

6.实现AT模式

1)AT模式快照生成和回滚动作都是由框架实现,没有任何代码侵入,因此实现非常简单。只不过,AT模式需要一个表记录全局锁,另一张表记录数据快照undo-log。

lock_table导入到TC服务关联的数据库:

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;


SET FOREIGN_KEY_CHECKS = 1;

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;

2)修改application.yml文件将事务模式改为AT模式即可

seata:
registry:
type: nacos
nacos:
server-addr: 192.168.136.160:8848
namespace: ""
group: DEFAULT_GROUP
application: seata-server
username: nacos
password: nacos
tx-service-group: seata-demo #事务组名称
service:
vgroup-mapping: # 事务组与cluster的映射关系
seata-demo: GZ
data-source-proxy-mode: AT

 

posted @ 2023-05-04 22:07  老王的日常  阅读(175)  评论(0)    收藏  举报