seata 如何开启tcc事物_Seata TCC-分布式事务解决时不得不考虑的问题

  • Post author:
  • Post category:其他


问题描述摘抄于 问题描述

并发控制

并发控制问题

问题描述:多个分布式事务去操作相同的记录

解决方案:将多个分布式事务操作的数据从修改同一条记录变成添加多条记录,这样的话commit/cancel阶段就不存在相互干扰问题了

空回滚

Seata空回滚问题

问题描述:

如图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因为丢包而导致的网络超时,此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,而 Cancel 操作调用未出现超时。

TCC 服务在未收到 Try 请求的情况下收到 Cancel 请求,这种场景被称为空回滚;空回滚在生产环境经常出现,用户在实现TCC服务时,应允许允许空回滚的执行,即收到空回滚时返回成功。

解决方案:

可以通过增加一个事务记录表,在try阶段最后往事务记录表中插入一条记录(xid-status)标记try阶段已经执行成功。二阶段的cancel操作去查询该记录表,假如记录不存在则属于空回滚,记录存在则属于正常的回滚,需要继续执行下去

防悬挂

Seata防悬挂问题

问题描述:

如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因网络拥堵而导致的超时,此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,Cancel 调用未超时;在此之后,拥堵在网络上的一阶段 Try 数据包被 TCC 服务收到,出现了二阶段 Cancel 请求比一阶段 Try 请求先执行的情况,此 TCC 服务在执行晚到的 Try 之后,将永远不会再收到二阶段的 Confirm 或者 Cancel ,造成 TCC 服务悬挂。

用户在实现 TCC 服务时,要允许空回滚,但是要拒绝执行空回滚之后 Try 请求,要避免出现悬挂。

解决方案:

可以通过增加一个事务记录表,在try阶段最后往事务记录表中插入一条记录(xid-status)标记cancel阶段已经执行过。此时try阶段进入时发现已经执行过回滚操作,则放弃try阶段的执行

ps:防悬挂问题下,用户在cancel阶段执行的同时,try阶段请求也进入。此时cancel和try都执行了

解决方案:可以通过增加一个redis分布式锁,保证一次性只能有一个线程能够对这次事务进行执行。而没有拿到分布式锁的线程等待持有锁的线程释放锁,再进行操作

幂等

Seata幂等问题

无论是网络数据包重传,还是异常事务的补偿执行,都会导致 TCC 服务的 Try、Confirm 或者 Cancel 操作被重复执行;用户在实现 TCC 服务时,需要考虑幂等控制,即 Try、Confirm、Cancel 执行一次和执行多次的业务结果是一样的。



版权声明:本文为weixin_30588427原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。