什么是Seata?

1 个回答

  • 念远怀人
    今朝有酒今朝醉,明日愁来明日愁。
    ### 一、什么是seata Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。其中AT模式是Seata主推的模式,是基于二阶段提交来实现的。 术语: **TC (Transaction Coordinator) 事务协调者** 维护全局和分支事务的状态,驱动全局事务提交或回滚。 **TM (Transaction Manager) - 事务管理器** 定义全局事务的范围:开始全局事务、提交或回滚全局事务。 **RM (Resource Manager) - 资源管理器** 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。 ### 二、AT模式的介绍 AT模式需要保证每个业务库,都有一张undo_log表,保存着业务数据执行前和执行后的镜像数据。 #### 1、前提条件 基于支持本地 ACID 事务的关系型数据库。 Java 应用,通过 JDBC 访问数据库。 #### 2、整体机制 两阶段提交协议的演变: 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。 二阶段: 提交异步化,非常快速地完成。 回滚通过一阶段的回滚日志进行反向补偿。 #### 3、读写隔离的实现 1、写隔离 一阶段本地事务提交前,需要确保先拿到 全局锁 。 拿不到 全局锁 ,不能提交本地事务。 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。 以一个示例来说明: 两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。 tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。 tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁 。 ![image.png](https://images.codewd.com/0ff4b5093151a2331b255c90efe913b8.png) tx1 二阶段全局提交,释放 全局锁 。tx2 拿到 全局锁 提交本地事务。 ![image.png](https://images.codewd.com/3aee2d6736310e6c2559d76c2d154619.png) 如果 tx1 的二阶段全局回滚,则 tx1 需要重新获取该数据的本地锁,进行反向补偿的更新操作,实现分支的回滚。 此时,如果 tx2 仍在等待该数据的 全局锁,同时持有本地锁,则 tx1 的分支回滚会失败。分支的回滚会一直重试,直到 tx2 的 全局锁 等锁超时,放弃 全局锁 并回滚本地事务释放本地锁,tx1 的分支回滚最终成功。 因为整个过程 全局锁 在 tx1 结束前一直是被 tx1 持有的,所以不会发生 脏写 的问题。 ### 2、读隔离 在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted) 。 如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。 ![image.png](https://images.codewd.com/2ad10f2765962b3f74a75568eacbd44e.png) SELECT FOR UPDATE 语句的执行会申请 全局锁 ,如果 全局锁 被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。这个过程中,查询是被 block 住的,直到 全局锁 拿到,即读取的相关数据是 已提交 的,才返回。 出于总体性能上的考虑,Seata 目前的方案并没有对所有 SELECT 语句都进行代理,仅针对 FOR UPDATE 的 SELECT 语句。
    发布于 2022-03-06 09:25 •IP属地 山东
    举报
    评论
    收藏1