分布式事务框架

一、阿里开源框架Seata

1.正常提交

2.回滚

 

  • Seata实现2PC要点

1、全局事务开始使用 @GlobalTransactional标识 。

2、每个本地事务方案仍然使用@Transactional标识。

3、每个数据都需要创建undo_log表,此表是seata保证本地事务一致性的关键。

二、TCC模型

  • Try 阶段:对应 2PC 中一阶段的准备提交事务(Prepare);
  • Confirm 阶段:对应 2PC 中二阶段事务提交(Commit)。默认 Confirm 阶段是不会出错的,只要 Try 成功,Confirm 一定成功;
  • Cancel 阶段:对应 2PC 中二阶段事务回滚(Rollback)。

1.空提交

对于空提交,出现的情况为:第一阶段TM调用RM超时或者下游返回明确失败,此时TM仍旧调用下游执行提交的第二阶段,这对于RM来说,由于并没有Prepare阶段,然后收到了Commit请求,这就是一次空提交,对于TCC模型来说,空提交为系统的bug,需要业务进行处理。

2.空回滚

如图所示,TM在调用下游服务的一阶段Prepare操作时,因为超时而导致下游服务并没有收到请求,此时,TM会触发二阶段回滚操作,调用下游服务执行Rollback操作,因为下游服务在没有收到Prepare请求的情况下收到Rollback请求,这种场景被称为空回滚。 空回滚在实际使用中可能会出现,而且被视为正常情况,在处理业务逻辑时需要处理。

3.事务悬挂

如图所示,TM在调用下游服务的一阶段Prepare操作时,可能因为各种原因而TM没有收到下游响应,此时TM会执行Rollback操作。而对于下游来说,可能存在的一种情况是:下游服务先收到了Rollback请求,执行了空回滚操作,然后又收到了Prepare请求,然后执行了Try操作,此时,该下游服务的事务状态将永远存在于Prepare阶段,这种情况就叫做事务悬挂。 对于事务悬挂,目前处理的做法是设置事务悬挂检测程序,检测下游服务处于Prepare状态而上游服务处于Rollback的事务,调用下游服务执行二次Rollbacki操作。

三、基于消息中间件

1.A处理事务时,先向消息中间件发送一条消息,中间件进行消息持久化并返回应答; 2.A收到应答后开始处理并提交事务,提交成功后向消息中间件发送Commit请求(此时消息有可能丢失,如果发丢,由消息中间件的事务回查机制完成) 3.消息中间件收到Commit请求后便向B投递该消息; 4.B收到后开始处理事务,处理成功后向消息中间件返回应答 5.如果向B投递的消息未送达,则消息中间件重新投递该消息

通过以上流程实现了类2pc的流程,此时的消息中间件充当了TM的角色。

注:消息中间件有一个回查任务,定期扫描非最终态的消息,进行回查

四、其他

1.RocketMQ事务消息

执行流程:
1、Producer向Broker端发送Half Message;
2、Broker ACK,Half Message发送成功;
3、Producer执行本地事务(executeLocalTransaction);
4、本地事务完毕,根据事务的状态,Producer向Broker发送二次确认消息,确认该Half Message的Commit或者Rollback状态。Broker收到二次确认消息后,对于Commit状态,则直接发送到Consumer端执行消费逻辑,而对于Rollback则直接标记为失败,一段时间后清除,并不会发给Consumer。正常情况下,到此分布式事务已经完成,剩下要处理的就是超时问题,即一段时间后Broker仍没有收到Producer的二次确认消息;
5、针对超时状态,Broker主动向Producer发起消息回查(checkLocalTransaction);
6、Producer处理回查消息,返回对应的本地事务的执行结果;
7、Broker针对回查消息的结果,执行Commit或Rollback操作,同Step4。

 

 

发表评论

邮箱地址不会被公开。 必填项已用*标注