python分布式事务框架_【SpringCloud】Spring Cloud Alibaba 之 Seata 分布式事务原理(三十七)...

Seata 分布式事务原理

Seata整体机制

两阶段提交协议的演变:

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。

二阶段:

提交异步化,非常快速地完成。

回滚通过一阶段的回滚日志进行反向补偿。

一阶段

过程:

1、解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息。

2、查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。

1 select id, name, since from product where name = 'TXC';

得到前镜像:

idnamesince

1

TXC

2014

3、执行业务 SQL:更新这条记录的 name 为 'GTS'。

4、查询后镜像:根据前镜像的结果,通过 主键 定位数据。

1 select id, name, since from product where id = 1;

得到后镜像:

idnamesince

1

GTS

2014

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 }

View Code

6、提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。

7、本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。

8、将本地事务提交的结果上报给 TC。

二阶段-回滚

1、收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。

2、通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。

3、数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理,详细的说明在另外的文档中介绍。

4、根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句:

1 update product set name = 'TXC' where id = 1;

5、提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

二阶段-提交

1、收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。

2、异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。

Seata原理机制验证

项目中TC、TM、RM关系如下:

一阶段-验证

1、调试启动项目,在order项目中,远程调用库存服务扣减库存前,增加断点

3、当程序运行到断点出,已经运行的创建订单业务,准备调用库存服务,查看数据库(order)中的数据

表order中,有一条数据

表undo_log,有一条数据

其中rollback_info,是一个json,里面内容如下:

beforeImage:表示前镜像,内容为空表示SQL执行前记录未创建

afterImage:表示后镜像,内容为SQL执行后,记录更新后的值

1 {2 "@class":"io.seata.rm.datasource.undo.BranchUndoLog",3 "xid":"192.168.1.4:8091:2013220742",4 "branchId":2013220749,5 "sqlUndoLogs":[6 "java.util.ArrayList",7 [8 {9 "@class":"io.seata.rm.datasource.undo.SQLUndoLog",10 "sqlType":"INSERT",11 "tableName":"`order`",12 "beforeImage":{13 "@class":"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords",14 "tableName":"order",15 "rows":[16 "java.util.ArrayList",17 [18

19 ]20 ]21 },22 "afterImage":{23 "@class":"io.seata.rm.datasource.sql.struct.TableRecords",24 "tableName":"order",25 "rows":[26 "java.util.ArrayList",27 [28 {29 "@class":"io.seata.rm.datasource.sql.struct.Row",30 "fields":[31 "java.util.ArrayList",32 [33 {34 "@class":"io.seata.rm.datasource.sql.struct.Field",35 "name":"id",36 "keyType":"PRIMARY_KEY",37 "type":-5,38 "value":[39 "java.lang.Long",40 10

41 ]42 },43 {44 "@class":"io.seata.rm.datasource.sql.struct.Field",45 "name":"user_id",46 "keyType":"NULL",47 "type":-5,48 "value":[49 "java.lang.Long",50 1

51 ]52 },53 {54 "@class":"io.seata.rm.datasource.sql.struct.Field",55 "name":"product_id",56 "keyType":"NULL",57 "type":-5,58 "value":[59 "java.lang.Long",60 1

61 ]62 },63 {64 "@class":"io.seata.rm.datasource.sql.struct.Field",65 "name":"count",66 "keyType":"NULL",67 "type":4,68 "value":10

69 },70 {71 "@class":"io.seata.rm.datasource.sql.struct.Field",72 "name":"money",73 "keyType":"NULL",74 "type":3,75 "value":[76 "java.math.BigDecimal",77 100

78 ]79 },80 {81 "@class":"io.seata.rm.datasource.sql.struct.Field",82 "name":"status",83 "keyType":"NULL",84 "type":4,85 "value":0

86 }87 ]88 ]89 }90 ]91 ]92 }93 }94 ]95 ]96 }

4、查看 seata 库的

branch_table 表

验证了向TC注册了分支

global_table 表

验证了全局事务ID

lock_table 表

验证了行锁

二阶段-回滚验证

1、当业务出错或超时回滚时,查看 order 库

order 表 :数据回滚

undo_log 表 :被清空、回滚

2、查看 seata 库的

branch_table 表:数据回滚、被清空

global_table 表:数据回滚、被清空

lock_table 表:数据回滚、被清空

验证二阶段回滚成功

二阶段-提交验证

1、当业务正常实现,事务提交,查看 order 库

order 表 :数据改变

undo_log 表 :数据被删除

2、查看 seata 库的

branch_table 表:数据被删除

global_table 表:数据被删除

lock_table 表:数据被删除

验证二阶段提交成功

你可能感兴趣的:(python分布式事务框架)