我使用的seata2.3版本。然后使用手写TCC的try、confirm、cancel做分布式事务操作。项目背景:order、account、storage三个微服务测试TCC事务回滚。order(TM)调用account、storage发起业务流程,因为误操作,代码写的垃圾storage项目总在TCC的rollback回滚操作,发生了业务悬挂。代码测试时间:2023-12-18 21:43:35;测试微服务接口路径:http://localhost:2001/order/create?userId=1&productId=1&count=10&money=100现在的问题:order、account服务重新启动没有问题,但是storage服务重启就会报空指针异常。productId的值为空。在seata的控制台中始终有一个分布式事务。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
根据您提供的信息,您的项目使用了 Seata 2.3 版本,并通过手写 TCC 的 try
、confirm
和 cancel
方法来实现分布式事务操作。在测试过程中,storage
微服务的 TCC 回滚操作频繁发生,导致业务悬挂问题。以下是针对该问题的详细分析和解决方案。
TCC(Try-Confirm-Cancel)模式是一种分布式事务解决方案,其核心思想是将事务分为三个阶段: - Try 阶段:预留资源,确保后续操作可以成功执行。 - Confirm 阶段:确认操作,提交 Try 阶段预留的资源。 - Cancel 阶段:回滚操作,释放 Try 阶段预留的资源。
在 Seata 中,TCC 模式的实现依赖于用户手动编写 try
、confirm
和 cancel
方法,并通过注解或配置将其注册到事务管理器中。
业务悬挂是指在分布式事务中,某些分支事务未能正确完成,导致全局事务无法正常结束。结合您的描述,以下是可能导致业务悬挂的原因:
storage
微服务的 try
方法执行失败(例如数据库连接异常、逻辑错误等),则 Seata 不会触发 confirm
或 cancel
方法,导致事务处于未完成状态。storage
微服务的 try
方法逻辑,确保其能够正确执行并返回成功状态。try
方法成功但 confirm
方法失败,Seata 会尝试调用 cancel
方法进行回滚。如果 cancel
方法本身存在逻辑问题(例如幂等性未处理好),可能会导致重复调用,进而引发业务悬挂。cancel
方法具有幂等性,避免因重复调用导致数据不一致。storage
微服务在 try
或 cancel
阶段因网络延迟或超时未能及时响应,Seata 可能会误判事务状态,导致业务悬挂。undo_log
表)来管理分布式事务的状态。如果 storage
微服务的事务日志记录失败或丢失,可能导致事务状态不一致。storage
数据库中的 undo_log
表,确保事务日志记录完整且无异常。storage
微服务的 TCC 实现try
方法能够正确预留资源,并返回成功状态。例如:
@Override
public boolean tryMethod(BusinessActionContext context) {
// 预留库存资源
int result = storageMapper.reserveStock(context.getActionContext("productId"), context.getActionContext("quantity"));
if (result > 0) {
return true; // 成功预留资源
}
throw new RuntimeException("库存不足");
}
cancel
方法具有幂等性,避免重复调用导致数据异常。例如:
@Override
public boolean cancelMethod(BusinessActionContext context) {
// 回滚库存资源
storageMapper.rollbackStock(context.getActionContext("productId"), context.getActionContext("quantity"));
return true;
}
application.properties
文件中,调整 Seata 的超时时间和重试次数配置:
seata.tm.commit-retry-count=5
seata.tm.rollback-retry-count=5
seata.tm.default-global-transaction-timeout=60000
storage
微服务的数据库连接池配置合理,避免因连接不足导致事务失败。storage
数据库中的 undo_log
表,确保事务日志记录完整。如果发现异常记录,可以手动清理或修复。logback.xml
或 log4j2.xml
中启用 Seata 的调试日志,查看事务执行过程中的详细信息:
<logger name="io.seata" level="DEBUG"/>
http://localhost:2001/order/create?userId=1
,确保 order
、account
和 storage
微服务的事务能够正常完成。storage
微服务的 try
方法中注入异常,验证 cancel
方法是否能够正确回滚。storage
微服务的 cancel
方法中模拟网络延迟,验证 Seata 是否能够正确处理超时问题。confirm
和 cancel
方法必须具有幂等性,避免因重复调用导致数据异常。undo_log
表的数据完整,避免因日志丢失导致事务状态不一致。通过以上步骤,您可以有效解决 storage
微服务的业务悬挂问题,并确保分布式事务的稳定性和可靠性。