请教个事务的问题

2023-05-19 12:06:31 +08:00
 craftx
举个例子,支付订单:
1. 将订单状态改为已支付
2. 记录支付数据
3. 调用库存服务的 http api 接口,减库存并发货

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

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

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

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

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

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


你的方案 1 中调用接口没必要一定要放到事务中把?
IDAEngine
2023-05-19 14:53:40 +08:00
sega 模式
7911364440
2023-05-19 15:05:41 +08:00
先执行 3 ,扣库存,库存扣失败直接返回,1 跟 2 直接放在本地事务就 ok 。
opengps
2023-05-19 15:23:35 +08:00
有个定义叫做“最终一致性”。关于原子性,只要你能保证最终一致性,就可以只在第一步进行控制,也算符合原子性操作
lincanbin
2023-05-19 15:40:23 +08:00
给订单加个锁,上锁期间禁止所有操作。
全部搞成功再解锁,然后定时去扫出来所有没全部成功的数据出来处理就好了。
wawaguo
2023-05-19 15:45:32 +08:00
3 改成扣库存 mq 消息,1 、2 、3 放同个事务,最后发送 mq 消息的时候报错就把 12 回滚,不报错就提交事务,需要做业务幂等
CantSee
2023-05-19 15:59:22 +08:00
哪那么多事,订单创建时候就锁定库存了,到时间再同步释放库存和取消订单,支付时候由于库存是已经锁定的了,只需要关注支付状态就可以了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/941201

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX