V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
craftx
V2EX  ›  问与答

请教个事务的问题

  •  
  •   craftx · 2023-05-19 12:06:31 +08:00 · 1832 次点击
    这是一个创建于 589 天前的主题,其中的信息可能已经有所发展或是发生改变。
    举个例子,支付订单:
    1. 将订单状态改为已支付
    2. 记录支付数据
    3. 调用库存服务的 http api 接口,减库存并发货

    以上三个操作,需要是一个原子操作,要么一起成功,要么一起失败。
    1 、2 好说,都是数据库操作,一个事务就 ok 。
    但 3 是另一个类型的操作。

    我想到方案是:
    1. 3 放在事务中,3 成功再提交事务,否则回滚。缺点是 3 会卡事务,只适用于流量特别低,3 执行很快的系统。
    2. 3 放队列中,失败了重试。缺点有 2:a ,放队列的操作也可能失败,除非放队列的操作也放事务中; b ,3 可能永远不会成功。
    16 条回复    2023-05-19 15:59:22 +08:00
    lthon
        1
    lthon  
       2023-05-19 12:23:49 +08:00 via Android
    这是分布式事务啊,看有没有大佬回答
    hhjswf
        2
    hhjswf  
       2023-05-19 12:26:20 +08:00 via Android
    @lthon 就这么点事用分布式事务,系统复杂度直接上一个等级
    dzdh
        3
    dzdh  
       2023-05-19 12:27:31 +08:00
    ID 密等

    有个协调者负责协调即可。或者是共同消费消息。
    zhuzhibin
        4
    zhuzhibin  
       2023-05-19 12:31:55 +08:00 via iPhone
    如果我请求外部接口中途被退出了,我方数据没有变更,外部系统数据变更了咋搞
    dzdh
        5
    dzdh  
       2023-05-19 12:52:37 +08:00
    httpapi 一般给两个接口。一个根据指定单号查询,一个下单,下单必传业务方自己的单号,并且返回服务的单号(流水号)

    下单前先按照业务方已经生成入库的单号进行查询,做同步,防止多下单。
    blackvv666
        6
    blackvv666  
       2023-05-19 13:08:55 +08:00
    mq 保障最终一致

    如果失败多次,直接转人工。
    sadfQED2
        7
    sadfQED2  
       2023-05-19 13:44:54 +08:00 via Android
    改一下执行顺序?先扣库存,扣成功了再改状态
    kylinC
        8
    kylinC  
       2023-05-19 14:12:54 +08:00
    最简单的方法是设置一个中间态, 1,2 成功了订单改为支付成功未发货,然后放队列执行 3, 定时检查支付成功未发货订单作为补充.缺点是时效性不高.
    wolfie
        9
    wolfie  
       2023-05-19 14:19:47 +08:00
    支付前,锁库存。
    取消支付 or 支付失败,回滚库存。
    wqq096737ink
        10
    wqq096737ink  
       2023-05-19 14:48:21 +08:00
    异步操作 ,线程 1 先扣库存 ,线程 2 执行事务,根据线程 1 的请求调用是否成功来决定是否提交事务。

    如果你觉得线程 2 需要等待线程 1 的结果造成线程 2 事务太长,那么就 扣库存-->订单事务 同步执行。


    你的方案 1 中调用接口没必要一定要放到事务中把?
    IDAEngine
        11
    IDAEngine  
       2023-05-19 14:53:40 +08:00
    sega 模式
    7911364440
        12
    7911364440  
       2023-05-19 15:05:41 +08:00
    先执行 3 ,扣库存,库存扣失败直接返回,1 跟 2 直接放在本地事务就 ok 。
    opengps
        13
    opengps  
       2023-05-19 15:23:35 +08:00
    有个定义叫做“最终一致性”。关于原子性,只要你能保证最终一致性,就可以只在第一步进行控制,也算符合原子性操作
    lincanbin
        14
    lincanbin  
       2023-05-19 15:40:23 +08:00
    给订单加个锁,上锁期间禁止所有操作。
    全部搞成功再解锁,然后定时去扫出来所有没全部成功的数据出来处理就好了。
    wawaguo
        15
    wawaguo  
       2023-05-19 15:45:32 +08:00
    3 改成扣库存 mq 消息,1 、2 、3 放同个事务,最后发送 mq 消息的时候报错就把 12 回滚,不报错就提交事务,需要做业务幂等
    CantSee
        16
    CantSee  
       2023-05-19 15:59:22 +08:00
    哪那么多事,订单创建时候就锁定库存了,到时间再同步释放库存和取消订单,支付时候由于库存是已经锁定的了,只需要关注支付状态就可以了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2492 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 04:42 · PVG 12:42 · LAX 20:42 · JFK 23:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.