概念
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata(Simple Extensible Autonomous Transaction Architecture) 是 阿里巴巴开源的分布式事务中间件,以高效并且对业务 0 侵入的方式,解决微服务场景下面临的分布式事务问题。
Seata是2019年开源的,Seata对高并发的性能要求比较高,希望事务跑起来速度一定要快,比如说LCN框架的3PC方案还是有锁的,所有性能不太好,同时LCN的TCC方案又业务侵入性比较大.
- Seata 实现分布式事务,关键角色UNDO_LOG(回滚日志记录表)
在每个应用需要分布式事务的业务库中创建这张表,这个表的核心作用是将业务数据在更新前后的数据镜像组织成回滚日志,保存在UNDO_LOG表中,以便业务异常能随时回滚
角色划分
RM(ResourceManager 资源管理者)理解为 我们的一个一个的微服务 也叫做事务的参与者.
TM(TranactionManager 事务管理者) 也是我们的一个微服务,但是该微服务是一个带头大哥,充当全局事务的发起者(决定了全局事务的开启,回滚,提交等)
凡是我们的微服务中标注了@GlobalTransactional ,那么该微服务就会被看出一个TM。我们业务场景中订单微服务就是一个事务发起者,同时也是一个RM
TC(全局事务的协调者):这里就是我们的Seata-server,用来保存全局事务,分支事务,全局锁等记录,然后会通知各个RM进行回滚或者提交.
架构
- 架构:TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端
设计思想
Seata设计思想是性能又高,对业务的侵入性又不大.每一个支持Seata事务的数据库建一张支撑Seata功能的回滚数据表.undo_log表,你在进行业务代码的时候,你做了insert操作的时候,Seata自动会给你生成一个对应的delete语句,你每进行一个insert操作,undo_log里面就会增加一个对应的delete操作的语句,如果说要回滚,就给undo_log表里面对应的delete语句拿出来自动回滚.
在协调者发送一个语句的时候,在第一个数据库的执行一条语句的时候,原本是要加lock锁的,但是在Seata的时候都不需要Lock,只需要在执行sql语句本身的时候自动生成一个逆向sql保存起来,如果在后面,你的协调者发送回滚请求的时候,第一个数据库直接把逆向sql拿出来回滚执行.
seata 的 AT 模式,采用的是大量运用在数据库软件的 Write Ahead Log 思想,即把事务的信息以事务日志的方式记录下来。
这种处理方式,实际上是对传统两阶段提交的一种改进和优化。主要有几个关键点:
1. 传统两阶段提交协议是阻塞协议,性能差
2. 传统两阶段提交协议高可用性不好
3. 传统两阶段提交协议的全局事务隔离机制不支持
4. 根据八二原则,80% 的涉及到全局事务的业务是能正常完成并提交的。
因此,在 AT 模式下,seata 采取的做法是,一个事务分支的数据库操作执行完后,马上进行本地事务的提交,从而释放相关的数据库资源。
分支事务中数据的 锁 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。
同时,随着本地事务结束, 连接 也得以释放。
分支事务中数据的 锁 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,锁 全局锁 才被持有至分支的 Phase2 结束。
分布式事务框架Seata事务处理过程描述
- A服务的TM 向 TC 申请开启(Begin)一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
- A服务的RM向TC注册分支事务
- A服务执行分支事务,对数据库做操作
- A服务开始远程调用B服务,并把XID 在微服务调用链路的上下文中传播。
- B服务的RM向TC注册分支事务,并将其纳入XID对应的全局事务的管辖
- B服务执行分支事务,向数据库做操作
- 全局事务调用链处理完毕,TM 根据有无异常向 TC 发起针对 XID 的全局提交(Commit)或回滚(Rollback)决议。
- TC 调度 XID 下管辖的全部分支事务完成提交(Commit)或回滚(Rollback)请求。
使用方式
- Seata和LCN一样,都带一个服务端,使用方式就是Windows启动Seata服务端的 seata-server.bat命令 ,如果是Linux系统的话就启动seata-server.sh命令.
2. 每个服务需要在file.conf里面配置这个项目连接Seata服务,
在file.conf那里的service模块的default.grouplist 那里配置服务端口值
3.在代码里面你需要使用Seata分布式事务的那个service实现类那里打一个@GlobalTransactional注解就可以了