阿里巴巴Seata分布式事务解决方案
Seata是什么
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
当开发框架为spring boot或者SSM,都可以使用Seata进行开发。
分布式事务是什么
在大型架构中,一般会把一个应用系统,从功能上划分为多个子服务或子项目。如上图所示,商城网站,当用户新增订单时:订单服务会新增一条订单记录,会员服务会更新用户的会员积分,库存服务会减少库存表的数量。
这三个操作,需要同时提交,或者同时回滚。这样的应用场景下,分布式事务就会产生了,这也是分布式事务所要做的操作。
事务协调者是什么
事务协调者的职责是向各个子服务下达命令,提交或者回滚事务。
当有一个请求到来时,事务协调者会通知各个子服务,开启事务,具体来说就是订单服务向数据库订单表新增一条订单记录。会员服务更新人员的会员积分。库存服务更新库存的余量。
操作完毕后,此时各个服务的事务都是未提交的状态。那在什么时候会进行事务的提交呢?当所有的子服务都把自己的事情做好了之后,向事务协调者回复说我已经操作完毕。当事务协调者收到所有事物反馈的信息后,确保都各个服务都已经处理完毕,然后再向各个子服务发送一个请求,命令各个子服务提交事务,到此,完成了各个服务数据写入操作。
分布式事务,三个重要角色
事务管理器(TM):决定什么时候全局提交/回滚(司令官)
事务协调者(TC):负责通知命令的中间件Seata-Server(传令官)
资源管理器(RM):做具体事情的工具人(大头兵)
三个角色相互配合,完成分布式事务的管理,具体过程如下:
在上面的示例中,商城应用就是TM,
新增订单操作,需要做三件事情,创建订单、增加积分、减少库存,使用Seata提供的@GlobalTransactional注解就可以将命令传达给TC,也就是我们自行安装的Seata服务,当TC接收到要开启全局事务的命令后,开始往下传达,传达给各个子服务,也就是RM。
对上图的示例伪代码进行说明,以订单服务为例,使用@Transactional注解,就会注册分支事务并开启本地事务。向订单表中新增一条订单记录,并提交本地事务,然后将完成的消息告诉TC。
此时TM得知三个服务均已处理完毕,会判断三个服务是否都正常执行完毕,如果都正常执行完毕,则下达全局提交的命令给TC,如果有任何一个或多个执行失败,则下达全局回归的命令给TC。
数据提交和回滚
在上一步提到的向订单表中新增一条订单记录,并提交事务。那么问题来了,如果其他的服务没有成功,Seata AT模式下如何实现数据整体回滚呢?
以上图为例,订单表在新增订单后提交事务后。Seata会往UNDO_LOG表(回滚表)插入一条逆向SQL。也就是删除记录的SQL。如果要执行回滚操作,实际上就是执行了这条逆向SQL。
积分表和库存表也是一样的逻辑。
数据脏读和脏写
如何避免并发场景的数据脏读和脏写?Seata使用了分布式锁的方式来解决这个问题。
如上图所示,同时对ID=1的数据执行更新操作,当tx1执行了更新,但未提交事务前,tx2一直处于等待状态。只有当tx1提交后,tx2才能更新。
上图是官方对脏读和脏写的处理方案。