分布式事务中某些节点必须成功的怎么办 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dzdh
V2EX    问与答

分布式事务中某些节点必须成功的怎么办

  •  
  •   dzdh 2021 年 11 月 10 日 1633 次点击
    这是一个创建于 1531 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如经典的转账场景

    a , 扣 10 成功 b , 加 10 成功 c , 调用银行接口(外部系统)出款成功

    如果 b 失败了 a,c 成功了。由于 C 无法回滚。A/B 必须成功,这种场景怎么办。

    10 条回复    2021-11-10 18:55:43 +08:00
    dongfuye1
        1
    dongfuye1  
       2021 年 11 月 10 日
    你可以这么设计,C 必须等待 AB 成功之后才能执行,这样保证了这个转账事务的 C 不需要回滚,只要 AB 完成后,就一定成功。

    我开源的分布式事务框架 https://github.com/yedf/dtm ,里面有一个并发 saga ,可以很方便的解决你的问题
    dzdh
        2
    dzdh  
    OP
       2021 年 11 月 10 日
    @dongfuye1 那要是多个外部系统呢都不可控呢
    kop1989
        3
    kop1989  
       2021 年 11 月 10 日
    @dzdh #2
    根据需求每分钟 /小时 /日定时做自动审计、对账工作。
    回滚只是一种异常情况下的逆处理,但未见得所有业务都支持逆向处理,这时候就需要审计程序来擦屁股。
    kop1989
        4
    kop1989  
       2021 年 11 月 10 日
    @dzdh #2
    这也是为什么很多重要业务的成功节点是“xx 分钟”、“24 小时”、“三个工作日”。
    dzdh
        5
    dzdh  
    OP
       2021 年 11 月 10 日
    @kop1989

    也就是说比如两个外部系统+一个本地系统的场景:

    1. 本地系统记账扣了多少钱从 xx 经销商
    2. 调用外部系统(银行)从 xx 供货商户头扣款
    3. 调用物流系统发货

    如果本地记账成功,扣款成功发货失败。
    xx 单位时间后 全局扫单吗 是扣退回款项还是补发货

    如果本地记账成功,扣款失败发货成功
    xx 单位时间后再扫单?

    那假设一种极端场景 外部系统之间相互冲突还都不能撤销 只能自己业务承担损失?
    dongfuye1
        6
    dongfuye1  
       2021 年 11 月 10 日
    @dzdh 我接触过的外部系统 api ,大致有以下三种情况:
    1. 一定能够执行成功,不支持回滚操作
    2. 业务有可能失败,也支持回滚操作
    3. 业务有可能失败,又不支持回滚操作

    大部分属于 1 、2 ,极少碰见 3 ,因为 3 这种是没办法协作的。一般像出款这类的业务,会通过 TCC 这种模式,先预留资源,变成 2 这种。
    kop1989
        7
    kop1989  
       2021 年 11 月 10 日
    @dzdh #5
    就像#6 说的,“失败,且不支持任何形式的逆操作,甚至不能手动对账审计”其实是极少场景。
    一般来讲,此类场景的做法是做异步结算。

    保证此场景一定是脱离主流程,且可容错的。
    akiasprin
        8
    akiasprin  
       2021 年 11 月 10 日
    普通的 2PC 感觉就可以?
    第一步协调者让 ABC 在本地把操作记录下来,并询问是否可以继续执行;
    ABC 返回结果后,进行第二步,协调者执行同步操作,让 ABC 把结果记录到本地,然后强制必须执行(第一步的询问过程后,ABC 都必须暂停对共享资源的其他事务处理,所以这次执行与第一步询问时所有状态是一致的)。
    akiasprin
        9
    akiasprin  
       2021 年 11 月 10 日
    @akiasprin 不过是外部系统,这个过程不可控的话,2PC 也不行。要么构建依赖同步关系(先 AB 成功再 C ),要么只能离线跑审计了。
    gamexg
        10
    gamexg  
       2021 年 11 月 10 日
    如果完全都不支持事务操作,那么这么实现:

    先执行 a ,扣款操作。确定 a 成功后,再执行 b 操作。确定 b 操作成功,在执行 c 操作。

    转账原则是,先执行扣款(有利于在自己的操作),后执行加款(有利于对方的操作),防止被人找到漏洞刷钱。

    你可以信任自己公司信誉,发现扣款,但是没给对方加款的话,你们公司会补偿对方。例如退款或者再次加款。

    但是不要信任对方,即使你目前的客户都是可信的,但是被人发现这个问题后,自会有专门干这行的去刷你的漏洞。

    对于失败,尝试重试,还是失败,这回滚之前的操作。例如,转账目标账号不存在,那么给来源账号加回去。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5455 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 03:39 PVG 11:39 LAX 19:39 JFK 22:39
    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