分布式事务(第05篇)分布式事务解决方法-TCC

NEWHOM 2020-03-04 03:05:00
原文地址:https://www.cnblogs.com/NEWHOM/p/12406326.html

一 什么是TCC

TCC将每个分支事务都分成三个部分(Try、Confirm、Cancel):

  • Try:业务检查及资源预留。
  • Confirm:真正执行业务,不做任何业务检查。使用Try阶段预留的资源。
  • Cancel:实现回滚操作,释放资源。

二 TCC实现分布式事务的流程

  1. 第一阶段:全局事务管理器分别调用所有分支事务,所有分支事务进行Try操作,当所有分支事务的Try操作都成功,或者某部分分支事务的Try操作失败,都进入第二阶段。
  2. 第二阶段:如果第一阶段所有分支事务Try都成功执行,则全局事务管理器通知所有分支事务进行Confirm操作,否则,通知所有分支事务进行Cancel操作。

成功图例:
![]()

失败图例:
![]()

三 举例说明TCC流程

场景:A账户给B账户转30块,AB在不同的服务。

方案1:

A服务:
    Try{
        检查A账户余额是否大于30元。
        A账户扣减30元。
    }

    Confirm{
        空。
    }

    Cancle{
        A账户增加30元。
    }
B服务:
    Try{
        B账户增加30元。
    }

    Confirm{
        空。
    }

    Cancle{
        B账户扣减30元。
    }

方案1存在的问题:

  1. 由于网络原因,A服务的Try没有执行,分支超时,则全局事务通知所有分支事务进行Cancel,那A账户就多了30元。
  2. Try、Confirm、Cancel都是有单独的线程去执行,且会出现重复调用,不支持幂等性。
  3. B服务执行Try后账户B增加了30元,其他服务将这30元使用了,后因为某种原因AB分支事务需要执行Cancel,B账户就不够30元了。
  4. 与1类型,B服务的Try没有执行,分支超时,则全局事务通知所有分支事务进行Cancel,那B账户就少了30元。

问题解决:

  1. A服务执行Cancel前判断A服务是否执行了Try。
  2. AB服务增加幂等性。
  3. B服务在Confirm中实现增加30元。
  4. B服务执行Cancel前判断B服务是否执行了Try。

优化后的方案2:

A服务:
    Try{
        增加幂等性。
        判断是否已经执行了Cancel。若Cancle已执行,则不执行Try,反之则执行Try。
        检查A账户余额是否大于30元。
        A账户扣减30元。
    }

    Confirm{
        空。
    }

    Cancle{
        增加幂等性。
        判断是否已经执行了Try。若Try未执行,则不执行Cancel,反之则执行Cancel。
        A账户增加30元。
    }
B服务:
    Try{
       空。 
    }

    Confirm{
        增加幂等性。
        B账户增加30元。
    }

    Cancle{
        空。
    }

由此我们可以发现使用TCC需要注意一些问题。

四 TCC需要注意的三种异常:

  1. 空回滚
    执行Cancel时需要判断当前分支事务是否已经执行Try。
  2. 悬挂
    执行Try时需要判断当前分支事务是否已经执行Cancel。
  3. 幂等性
    由于Confirm和cancel失败需进行重试,因此需要实现幂等性。

五 TCC与2PC区别

TCC本质上也是二阶段提交协议,但他们又有很大不同:

  • TCC作用与服务层,2PC作用于资源层。(TCC开发人员通过业务代码实现数据提交与回滚,2PC基于数据库厂商原生协议,由数据库层面实现数据提交与回滚。)
  • TCC三个接口逻辑由开发人员编写,2PC由数据库厂商或第三方编写。
  • 由于以上两原因,TCC可以自由控制资源锁定的粒度。
  • TCC侵入业务逻辑过强,每个分支事务都需要实现Try、Confirm、Cancel三个接口,改造成本高。

六 TCC缺点

  • 代码侵入性太强,每个分支事务都得实现Try、Confirm、Cancel。(这一点我可难了,代码量庞大,耦合性高..手动狗头)
  • 幂等性难以控制。

七 TCC的实现框架

ByteTCC,TCC-transaction,Hmily。

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。