【分布式事务系列】 AT模式-第一阶段实现原理

193 阅读2分钟

这是我参与2022首次更文挑战的第10天,活动详情查看2022首次更文挑战

Seata AT模式的实现原理

AT模式是基于XA事务模型演进而来的,它的整体机制是一个改进版的两阶段提交协议。

  • 第一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
  • 第二阶段:提交异步化,快速完成,回滚通过第一阶段的回滚日志进行反向补偿。
AT模式第一阶段的实现原理

在业务流程中执行库存扣减操作的数据库操作,Seata会基于数据源代理对原执行的SQL进行解析,代理的配置代码如下(Seata 0.9.0版本后支持自动代理)

@Bean
public DataSourceProxy DataSourceProxy(DruidDataSource druidDataSource){
    return new DataSourceProxy(druidDataSource);
}

将业务数据在更新数据前后保存在undo_log日志表中,利用本地事务的ACID特性,把业务数据的更新和回滚日志写入同一个本地事务中进行提交,完整的执行流程如下图所示:

image-20220129155748739.png

库存表结构

idproduct_codenamecount
120220129160001鼠标1000
220220129160002键盘500

AT分支事务业务逻辑是

update stock set count = count - 1 where product_code = "20220129160002" 

第一阶段的执行逻辑

  • 通过DataSourceProxy对业务SQL进行解析,得到SQL类型(update)、表(stock)、条件(where product_code = "20220129160002" )等相关的信息。

  • 查询修改之前的数据镜像,根据解析得到的条件信息生成查询语句,定位数据。

    select id,product_code,name,count from stock where product_code = "20220129160002"
    

    查询获取产品对应的库存数量为1000。

  • 执行业务SQL,更新记录的count=count-1

  • 查询修改后的数据镜像,根据前镜像的结果,通过主键定位数据。

    select id,product_code,name,count from stock where id = 2
    

得到修改后的镜像数据count=999。

  • 插入回滚日志,把前、后镜像数据及业务SQL相关的信息组成一条回滚日志记录,插入undo_log表中,可在对应库的undo_log表中获得数据。

    undo_log表数据如下:

    idbranch_idxidcontextrollback_infolog_statuslog_createdlog_modified
    12022012916220110.0.101.175:8091:202201291623serializer=jackson(BLOB)02022-01-29 16:26:392022-01-29 16:26:39

    注意:rollback_info标识回滚的数据包含beforeImage和afterImage。

  • 提交前,向TC注册分支事务,申请stock表主键值等于1的记录的全局锁。

  • 本地事务提交:业务数据的更新和生成的undo_log一并提交。

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