用 Node 轻松完成一个 TCC 分布式事务,保姆级教程 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dongfuye1
V2EX    推广

用 Node 轻松完成一个 TCC 分布式事务,保姆级教程

  •  7
     
  •   dongfuye1 2021-08-30 13:48:23 +08:00 5896 次点击
    这是一个创建于 1508 天前的主题,其中的信息可能已经有所发展或是发生改变。

    什么是 TCC,TCC 是 Try 、Confirm 、Cancel 三个词语的缩写,最早是由 Pat Helland 于 2007 年发表的一篇名为《 Life beyond Distributed Transactions:an Apostate’s Opinion 》的论文提出。

    TCC 组成

    TCC 分为 3 个阶段

    • Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
    • Confirm 阶段:如果所有分支的 Try 都成功了,则走到 Confirm 阶段。Confirm 真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源
    • Cancel 阶段:如果所有分支的 Try 有一个失败了,则走到 Cancel 阶段。Cancel 释放 Try 阶段预留的业务资源。

    TCC 分布式事务里,有 3 个角色,与经典的 XA 分布式事务一样:

    • AP/应用程序,发起全局事务,定义全局事务包含哪些事务分支
    • RM/资源管理器,负责分支事务各项资源的管理
    • TM/事务管理器,负责协调全局事务的正确执行,包括 Confirm,Cancel 的执行,并处理网络异常

    如果我们要进行一个类似于银行跨行转账的业务,转出( TransOut )和转入( TransIn )分别在不同的微服务里,一个成功完成的 TCC 事务典型的时序图如下:

    image.png

    TCC 网络异常

    TCC 在整个全局事务的过程中,可能发生各类网络异常情况,典型的是空回滚、幂等、悬挂,由于 TCC 的异常情况,和 SAGA 、可靠消息等事务模式有相近的地方,因此我们把所有异常的解决方案统统放在这篇文章《分布式事务最经典的七种解决方案》的子事务屏障环节进行讲解

    TCC 实践

    下面我们进行一个 TCC 事务的具体开发

    目前可用于 TCC 的开源框架,主要为 Java 语言,其中以 seata 为代表。我们的例子采用 nodejs,使用的分布式事务框架为 dtm,它对分布式事务的支持非常优雅。下面来详细讲解 TCC 的组成

    下面我们来编写具体的 Try/Confirm/Cancel 的处理函数

    router.post('/api/TransOutTry', (ctx, next) => { console.log("TransOutTry") ctx.body = { result: "SUCCESS" } }).post('/api/TransOutConfirm', (ctx, next) => { console.log("TransOutConfirm") ctx.body = { result: "SUCCESS" } }).post('/api/TransOutCancel', (ctx, next) => { console.log("TransOutCancel") ctx.body = { result: "SUCCESS" } }).post('/api/TransInTry', (ctx, next) => { console.log("TransInTry") ctx.body = { result: "SUCCESS" } }).post('/api/TransInConfirm', (ctx, next) => { console.log("TransInConfirm") ctx.body = { result: "SUCCESS" } }).post('/api/TransInCancel', (ctx, next) => { console.log("TransInCancel") ctx.body = { result: "SUCCESS" } }) 

    到此各个子事务的处理函数已经 OK 了,然后是开启 TCC 事务,进行分支调用

    async function FireTcc() { let dtm = "http://localhost:8080/api/dtmsvr" // dtm 服务地址 let svc = "http://localhost:4005/api" // 本地服务前缀 // 开启一个 tcc 事务,第二个参数里面,写全局事务的逻辑 await dtmcli.tccGlobalTransaction(dtm, async (t) => { let req = { amount: 30 } // 子事务需要的负荷 console.log("calling trans out") // 注册事务分支,并调用分支中的 Try await t.callBranch(req, svc + "/TransOutTry", svc + "/TransOutConfirm", svc + "/TransOutCancel") console.log("calling trans in") // 注册事务分支,并调用分支中的 Try await t.callBranch(req, svc + "/TransInTry", svc + "/TransInConfirm", svc + "/TransInCancel") }) } 

    至此,一个完整的 TCC 分布式事务编写完成。

    如果您想要完整运行一个成功的示例,那么参考这个例子 yedf/dtmcli-node-sample,将它运行起来非常简单

    # 部署启动 dtm # 需要 docker 版本 18 以上 git clone https://github.com/yedf/dtm cd dtm docker-compose up # 另起一个命令行 git clone https://github.com/yedf/dtmcli-node-sample cd dtmcli-node-sample npm install node . 

    TCC 的回滚

    假如银行将金额准备转入用户 2 时,发现用户 2 的账户异常,返回失败,会怎么样?我们给出事务失败交互的时序图

    image.png

    这个跟成功的 TCC 差别就在于,当某个子事务返回失败后,后续就回滚全局事务,调用各个子事务的 Cancel 操作,保证全局事务全部回滚。

    小结

    在这篇文章里,我们介绍了 TCC 的理论知识,也通过一个例子,完整给出了编写一个 TCC 事务的过程,涵盖了正常成功完成,以及成功回滚的情况。相信读者通过这边文章,对 TCC 已经有了深入的理解。

    关于分布式事务更多更全面的知识,请参考《分布式事务最经典的七种解决方案》

    文中使用的例子节选自yedf/dtm,支持多种事务模式:TCC 、SAGA 、XA 、事务消息 跨语言支持,已支持 golang 、python 、Java 、PHP 、nodejs 等语言的客户端,参考各语言 SDK。提供子事务屏障功能,优雅解决幂等、悬挂、空补偿等问题。

    阅读完此篇干货,欢迎大家访问https://github.com/yedf/dtm项目,给颗星星支持!

    23 条回复    2021-09-07 21:19:26 +08:00
    gopher432109
        1
    gopher432109  
       2021-08-30 14:08:00 +08:00
    不错!
    dk7952638
        2
    dk7952638  
       2021-08-30 16:25:13 +08:00
    看着挺不错的,请问有计划对 Java 进行支持么
    dongfuye1
        3
    dongfuye1  
    OP
       2021-08-30 16:48:42 +08:00
    已有 Java 的支持,参见链接: https://dtm.pub/summary/code.html#go
    jinwu
        4
    jinwu  
       2021-08-31 09:53:15 +08:00
    好东西,已 Star
    dongfuye1
        5
    dongfuye1  
    OP
       2021-08-31 14:00:55 +08:00
    @gopher432109 谢谢支持
    dongfuye1
        6
    dongfuye1  
    OP
       2021-08-31 14:01:06 +08:00
    @jinwu 谢谢支持
    mutoudaren
        7
    mutoudaren  
       2021-09-01 12:20:04 +08:00 via Android
    请问这个有什么简单的使用场景吗?
    dongfuye1
        8
    dongfuye1  
    OP
       2021-09-01 13:13:04 +08:00
    @mutoudaren 使用场景可以参考我之前的文章 t/796220
    usboy
        9
    usboy  
       2021-09-01 13:30:57 +08:00
    妙啊
    charexcalibur
        10
    charexcalibur  
       2021-09-01 13:38:08 +08:00
    好东西,本来想给个 star 的 结果发现早就 star 过了,只能双击 star 再支持一下
    dongfuye1
        11
    dongfuye1  
    OP
       2021-09-02 18:02:55 +08:00
    @usboy 谢谢支持
    dongfuye1
        12
    dongfuye1  
    OP
       2021-09-02 18:03:07 +08:00
    @charexcalibur 谢谢支持
    shilianmlxg
        13
    shilianmlxg  
       2021-09-02 22:18:11 +08:00 via iPhone
    想学 node. 写写大佬。 希望大佬再多写亿点点博客
    dongfuye1
        14
    dongfuye1  
    OP
       2021-09-02 22:44:52 +08:00
    @shilianmlxg 你是啥原因想学 node,现在国内用 node 写后端的越来越少
    flyingfz
        15
    flyingfz  
       2021-09-03 10:00:17 +08:00
    我们就是用 nodejs 写后端的。 :)
    dongfuye1
        16
    dongfuye1  
    OP
       2021-09-03 10:22:09 +08:00
    @flyingfz 我在创业公司也是,但是用 node 的人是在太少了,很难招到有 node 经验的候选人
    flybluewolf
        17
    flybluewolf  
       2021-09-03 16:32:06 +08:00
    我司 2014 开始 node 全线后台到至今,挺好的
    dongfuye1
        18
    dongfuye1  
    OP
       2021-09-03 19:45:33 +08:00
    @flybluewolf 我这也是全部用 node,并发、开发效率、强类型各个方面都很好,就是难招聘到合适的候选人
    flyingfz
        19
    flyingfz  
       2021-09-06 09:27:23 +08:00
    @dongfuye1 没有办法, 我们都是用 java 的名义面试, 然后面试时说清楚主要用 nodejs,
    dongfuye1
        20
    dongfuye1  
    OP
       2021-09-06 09:34:02 +08:00
    @flyingfz 我们也一样,选择的主语言是 PHP,现在 PHP 愿意转其他语言的人更多
    eggggg2han
        21
    eggggg2han  
       2021-09-07 15:05:15 +08:00
    厉害,但是看不懂哈哈哈
    eggggg2han
        22
    eggggg2han  
       2021-09-07 15:05:34 +08:00
    老铁找工作不
    dongfuye1
        23
    dongfuye1  
    OP
       2021-09-07 21:19:26 +08:00
    @eggggg2han 大致什么样的工作,是在北京吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4465 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 01:03 PVG 09:03 LAX 18:03 JFK 21:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86