seata分布式事务解决方案

一 什么是seata

前言:seata我之前在生产中用过几次,但是不可避免,其确实存在写性能上的问题,后续只能在seata的基础上完善成增加异步处理+最终一致性的解决方案,所以没有什么架构是完美的。

先通过如下的图,大致了解一下seata的架构:

![image](images/C_BkXtHwVwZMDKfCWeJmGaHnC9KO_NC66E2MPPXOq9w.jpeg)

我做一个简短的总结,然后再仔细的讲解:

seata主要构成可以简单记忆为:,三组件+一个Id:

全局id: transactionId 全局唯一事务ID

三组件:

 TC - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚,大白话:负责通知命令的中间件Seata-Server(传令官)

TM - 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务,大白话:决定什么时候全局提交/回滚(司令官)

RM - 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚,大白话:做具体事儿的工具人(大头兵)

接下来我们详细了解一下seata:

看一下如下的场景,如果在单一系统或者项目中,肯定直接使用事务注解就可以实现,但是微服务场景下,每个项目都是自己独立的库,就不太好解决了。

![image](images/rGfFy0itgusq1vyG4Ntb74f00jfsVv-QFWFQoBvtoRQ.png)

二 传统的分布式事务

![image](images/SJccj_i6FA1DMpI4kS1AkkplAVjYcjokwf4V_iTFzy4.png)

TC作为事务协调者,其最大的作用就是与每一个子事务进行通讯,通讯是分为几步的:

前提:子模块的TM来TC注册,告诉我当前事务是需要参与分布式事务的,获取到XID

  1. 任务来临,TC通知对应的子模块,开始处理你的事务,并告知我结果
  2. 子模块处理成功后,并不会自动提交
  3. TC收到所有此XID的所有成功的响应
  4. TC通知所有模块提交

注意:此过程我们提交了两次,一次是向TC成功的信息,一次是自己数据的正式提交,所以称为2PC,二阶段提交。

三 seata

前言: 如何搭建配置seata请看我的springCloud ALiababa专题。

我们先看看如何开启一个分布式事务:

![image](images/VMyhyf7JinxnVW4e1LRlFQk65DcGJhLiG9GnjSUf7f8.png)

GlobalTransactional是seata提供开起事务的注解。

后续步骤:

![image](images/X1PUyvUvSVg6EXK-hHaHW2d073xWpVyX1YfqT8X3jvM.png)

此处跟传统的处理方式不同:

  1. 本地成功后,会在本地立即提交

后续:

![image](images/Fqe7BUge5S2a1k8913-EAgEUgdvwie3rMxtYHvvNFMk.png)

后续:

![image](images/NtjwQv8BxEvZENzD0BHEmaraV9-PWsP4Iu_FyHZcvMg.png)

四 seata如何实现的回滚的?

前言:此处是at模式

原理:seata的每个rm其实都建立了一张UNDO_LOG的表,此表记录了事务执行的回滚sql记录。

如下图:

![image](images/mMfLJa7kB_Z53x_-bKHhyzD4APGQ1gnO6QAyQGjE9Qg.png)

![image](images/4Y6ohZaKfX8Moi_AXFbmIb5Rh9khmdGYoRSMw6z0Nwk.png)

![image](images/XKrc75D2Yig0-jbVLkSfh60CNQZo2vE2EhNxWoRLd1k.png)

五 seata怎么处理并发,脏数据的?

脏数据概要总结:

分阶段:

before image

    执行sql

    after image

    生成行锁

    提交 生成undo日志

    如果提交成功

    就会删除bi ai 解锁

    如果提交失败

    校验脏写 校验ai 和 当前数据库是否一致

    如果一致 证明数据没有被别人修改 直接还原bi 同时异步的执行和删除

    如果不一致 则需要人工处理/ 如果你加了分布式锁 则不需要人工处理

基于以上概要流程,我们来看下图:

![image](images/IEpZT0myRRFHPqA_bvyRUqIfss35WGdS4VQEDFbySzc.png)

    讲解并发:

  1. tc自带分布式锁
  2. tx1进来的时候,如果当前事务没有处理完成,会给当前数据增加全局锁
  3. tx2进来,如果当前数据具备全局锁,就会一直处理等待状态
  4. tx1释放锁
  5. tx2获取锁

总结:

image

Last modification:July 5, 2022
If you think my article is useful to you, please feel free to appreciate