侧边栏壁纸
博主头像
清如许博主等级

努力成长为一颗大树,一半洒落阴凉,一半沐浴阳光,非常沉默非常骄傲,从不依靠从不寻找

  • 累计撰写 58 篇文章
  • 累计创建 36 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

带你读透 SEATA 的 AT 模式.md

清如许
2022-06-10 / 0 评论 / 0 点赞 / 36 阅读 / 2,355 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-06-10,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

|---|---
id| bigint(20)| PRI
name| varchar(100)|
since| varchar(100)|

AT 分支事务的业务逻辑:

update product set name = 'GTS' where name = 'TXC';

执行阶段

过程:

  1. 解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = ‘TXC’)等相关的信息。
  2. 查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。
select id, name, since from product where name = 'TXC';

得到前镜像:

idnamesince
1TXC2014
  1. 执行业务 SQL:更新这条记录的 name 为 ‘GTS’。
  2. 查询后镜像:根据前镜像的结果,通过 主键 定位数据。
select id, name, since from product where id = 1`;

得到后镜像:

idnamesince
1GTS2014
  1. 插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
{
    "branchId": 641789253,
    "undoItems": [{
        "afterImage": {
            "rows": [{
                "fields": [{
                    "name": "id",
                    "type": 4,
                    "value": 1
                }, {
                    "name": "name",
                    "type": 12,
                    "value": "GTS"
                }, {
                    "name": "since",
                    "type": 12,
                    "value": "2014"
                }]
            }],
            "tableName": "product"
        },
        "beforeImage": {
            "rows": [{
                "fields": [{
                    "name": "id",
                    "type": 4,
                    "value": 1
                }, {
                    "name": "name",
                    "type": 12,
                    "value": "TXC"
                }, {
                    "name": "since",
                    "type": 12,
                    "value": "2014"
                }]
            }],
            "tableName": "product"
        },
        "sqlType": "UPDATE"
    }],
    "xid": "xid:xxx"
}
  1. 提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。
  2. 本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。
  3. 将本地事务提交的结果上报给 TC。

完成阶段-回滚

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

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

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

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

update product set name = 'TXC' where id = 1;
  1. 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

完成阶段-提交

  1. 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
  2. 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。

和 XA 的关系

前面一直拿 AT 和 XA 做比较。

这里特别说明一下,并不是说 XA 协议本身有问题,只是说在某些场景的需求下,基于 XA 做不理想。

但同样,另外还有一些对内外部 一致性要求非常高 的场景,可能 XA 又是非常适合,甚至必需的。

这也是接下来 Seata 将提供 XA 模式的原因。

关于 XA 模式 这里就不展开了,后面会有专门的文章和大家交流。

AT 的核心价值

AT 模式到底带给我们什么价值呢?

首先,从技术原理角度来看,非常重要的一点是: 平衡

![Balance](https://img-
blog.csdnimg.cn/eeaef401004c4f5abbb984684620b3ef.png?x-oss-
process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn5qCR5YWI55SfLg==,size_20,color_FFFFFF,t_70,g_se,x_16)

必须承认,分布式事务是个复杂的问题,目前还没有任何一种解决方案可以非常完美地适应所有应用场景。

如果把分布式事务方案按 一致性性能易用性 这 3 个维度来考量:AT
模式,实际上是在业务需求允许的前提下,找到一个比较好的平衡点。

编程模型不做改变的前提下,达到确定的一致性,而且保证了性能和系统可用性。

其次,从用户的角度来看。我们设想一个企业业务的成长过程:

![Demo Business Growth](https://img-
blog.csdnimg.cn/34294bbe906c4358a3f815ae16ebeeac.png?x-oss-
process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn5qCR5YWI55SfLg==,size_20,color_FFFFFF,t_70,g_se,x_16)

  • 1.0:单体应用,快速上线,这个时候完全不涉及分布式事务。

  • 2.0:单个数据库无法支撑,数据分布到多个数据库,产生分布式事务问题。

  • 3.0:微服务化,进一步产生跨服务的分布式事务。

  • 4.0:跨应用的整合,成为 SaaS 或 FaaS 的平台,在更大的范围,产生分布式事务问题。

基于 Seata 的 AT 模式构建企业业务的分布式事务解决方案,可以带来以下 3 个方面的 核心价值

  • 低成本编程模型 不变,轻依赖 不需要为分布式事务场景做特定设计,业务像搭积木一样自然地构建成长。
  • 高性能 :协议 不阻塞 ;资源释放快,保证业务的吞吐。
  • 高可用 :极端的异常情况下,可以暂时 跳过异常事务 ,保证整个业务系统的高可用。

AT 的现在和未来

没有 银蛋 ,AT 模式带来上面提到的价值的同时,也必定有一些局限和不足。

较重的 SDK

![Heavy SDK](https://img-
blog.csdnimg.cn/a9655036309640d0919f8402836cce67.png?x-oss-
process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn5qCR5YWI55SfLg==,size_20,color_FFFFFF,t_70,g_se,x_16)

AT 模式有很大一部分功能依赖于 SDK 的实现,包括 SQL 解析、回滚日志的生成、分支提交回滚逻辑的执行等等。

这些关键运行机制是基于 Java 的 JDBC 构建起来的。如果要支持其他语言,迁移成本非常高。

面向云原生时代,AT 模式未来的方向将是 SDK 的轻量化和标准化,把大部分能力下沉到代理层(Agent 或 Sidecar 的形式),让应用只需要很简单的
SDK 和标准的 SQL 就可以工作。

![Light SDK](https://img-
blog.csdnimg.cn/a94c8de8b5624b5b9da2d438b6284340.png?x-oss-
process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn5qCR5YWI55SfLg==,size_20,color_FFFFFF,t_70,g_se,x_16)

能力边界

从工作原理来看,AT 模式有一些特定的使用条件和局限。

首先,AT 模式的 基本条件 是:数据库本身必须支持 本地事务 。AT 的基本工作机制是基于本地事务的。

其次,数据表必须定义 主键 。回滚日志的生成和使用,是基于数据主键的。

另外, 隔离性 ,这也是所有基于 补偿
的分布式事务解决方案,都面临的问题:隔离性很难做到很高,或者说,要做到较高隔离性的成本和收益是不匹配的。

基于这些目前的局限,Seata 项目整体的应对策略是,提供各类不同的事务模式来取长补短,实现全场景的覆盖。

目前已经具备和正在规划中的,一共是两大类,4 种事务模式:

![Landscape of Seata](https://img-
blog.csdnimg.cn/58f0a43264364c93ae364367752bdb10.png?x-oss-
process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aSn5qCR5YWI55SfLg==,size_20,color_FFFFFF,t_70,g_se,x_16)

  • 业务无侵入的:AT、XA

  • 业务侵入的:TCC、Saga

这些模式各自有其适用和不适用的场景,Seata 将把这些模式很好地融合起来,给用户提供一站式的解决方案。

总结

Seata 的 AT 模式是分布式架构演进过程中,分布式事务中间件在阿里巴巴实践的创造性解决方案。

Seata 的 AT 模式基于本地事务的特性,通过拦截并解析 SQL 的方式,记录自定义的回滚日志,从而打破 XA 协议阻塞性的制约,在一致性、性能、易用性
3 个方面取得平衡:在达到确定一致性(非最终一致)的前提下,即保障较高的性能,又能完全不侵入业务。

在绝大部分应用场景下,Seata 的 AT 模式都能很好地发挥作用,把应用的分布式事务支持成本降到极低的水平。

对于一些不适用 AT 模式的场景,Seata 也提供其他几类主流的分布式事务解决方案来补齐。

附录

作者:sharajava
链接:https://www.jianshu.com/p/0ed828c2019a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0

评论区