绯闻热词
角色划分:
RM(ResourceManager 资源管理者)
理解为 我们的一个一个的微服务 也叫做事务的参与者.TM(TranactionManager 事务管理者)
也是我们的一个微服务,但是该微服务是一个带头大哥,充当全局事务的发起者(决定了全局事务的开启,回滚,提交等) ***凡是我们的微服务中标注了@GlobalTransactional ,那么该微服务就会被看出一个TM。我们业务场景中订单微服务就是一个事务发起者,同时也是一个RMTC(全局事务的协调者):
这里就是我们的Seata-server,用来保存全局事务,分支事务,全局锁等记录,然后会通知各个RM进行回滚或者提交.二话不多说,上图
内幕揭秘(工作原理)
执行业务SQL update product set name = 'GTS' where name = 'TXC';
第一阶段:
1:解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where id='1')等相关的信息。 2:查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。select id, name, since from product where name = 'TXC';3:执行业务 SQL:更新这条记录的 name 为 'GTS'。update product set name = 'GTS' where name = 'TXC'; 4:查询后镜像:根据前镜像的结果,通过 主键 定位数据select id, name, since from product where id = 1`;
5:插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中
1 { 2 "branchId": 641789253, 3 "undoItems": [{ 4 "afterImage": { 5 "rows": [{ 6 "fields": [{ 7 "name": "id", 8 "type": 4, 9 "value": 1 10 }, { 11 "name": "name", 12 "type": 12, 13 "value": "GTS" 14 }, { 15 "name": "since", 16 "type": 12, 17 "value": "2014" 18 }] 19 }], 20 "tableName": "product" 21 }, 22 "beforeImage": { 23 "rows": [{ 24 "fields": [{ 25 "name": "id", 26 "type": 4, 27 "value": 1 28 }, { 29 "name": "name", 30 "type": 12, 31 "value": "TXC" 32 }, { 33 "name": "since", 34 "type": 12, 35 "value": "2014" 36 }] 37 }], 38 "tableName": "product" 39 }, 40 "sqlType": "UPDATE" 41 }], 42 "xid": "xid:xxx" 43 }6:提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。 7:本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。 8:将本地事务提交的结果上报给 TC。
二阶段-回滚
1:收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作 2:通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。 3:数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改 4:根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句: 5:提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC二阶段-提交
1:收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。 2:异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。