Seata简介
介绍
一阶段:事务协调者通知每一个服务处理本地事务,每个服务开始处理但是不会提交事务,处理完毕后告知协调者。
二阶段:协调者收到所有服务的消息后通知他们提交事务。
重要角色
事务管理器(TM),决定什么时候全局提交or回滚。(司令官)
事务协调者(TC),负责通知命令的中间件seata-server。(传令官)
资源管理器(RM):执行具体事情。(大头兵)
Seata AT模式下如何实现数据自动提交和回滚
在数据库里中添加undolog表:
-
如果全局事务成功,删除undolog即可。
-
如果全局事务失败,执行undolog的逆向SQL
Seata如何避免并发场景的脏读与脏写
写隔离
-
一阶段本地事务提交前,需要确保先拿到 全局锁 。
-
拿不到 全局锁 ,不能提交本地事务。
-
拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
读隔离
在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离
级别是 读未提交(Read Uncommitted) 。
如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE 语句的代理。
SELECT FOR UPDATE 语句的执行会申请 全局锁 ,如果 全局锁 被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。这个过程中,查询是被 block 住的,直到 全局锁 拿到,即读取的相关数据是 已提交 的,才返回。
出于总体性能上的考虑,Seata 目前的方案并没有对所有 SELECT 语句都进行代理,仅针对 FOR UPDATE 的 SELECT 语句。
实践
创建3个微服务:会员,库存,订单。
订单服务的下订单方法里有三个事务方法,下订单,会员加积分,减库存。通过feign远程调用其他两个服务,globaltransaction注解声明全局事务,可以全局提交or回滚。