批量支付 1000 笔以上运单

39 天前
 loszhang
我们客户现在有个需求,需要支持一次请求可以发起 1000 笔以上运单的支付,主要集中在月底,大概有 6 万以上的运单。目前我们支持的最大数量是 200 笔,是同步请求,就是一次请求,会把运单的状态修改为支付处理中,修改钱包,记录运单状态的其他数据,大概每笔运单需要修改或者新增 5 张表,然后向 mq 写入一条支付消息,用于向支付平台发起支付的请求,这是一笔运单需要做的,最后会把这 200 笔运单结果返回给前端,实际的支付会由 mq 去处理。现在如果要处理 1000 笔以上的运单,肯定不能再用同步请求,主要就是把这 1000 笔运单记录下来,修改状态,不能让客户将这 1000 笔运单再发起一次支付请求。不知道大家有没有好的处理方案。
1841 次点击
所在节点    Java
33 条回复
wolfan
39 天前
前端给个加载打印的,就一行一行打印成交信伪装成处理,后台分批提交 6W 单不就好了。
loszhang
39 天前
@wolfan 我们现在的方案是,前端发起请求后,后端直接返回类似交易已受理的结果,前端不用再等待后端对这笔请求中 1000 笔运单的一个预处理(修改运单状态及相关表),因为这个太耗时,所以我们后端接收到这 1000 笔运单后,先记录下 1000 笔运单的 id ,异步去处理,但是在这处理这笔运单时,客户还会继续发起下一次 1000 笔运单的支付请求,这个 1000 笔运单中,肯定会有上次请求还未来得及修改运单状态的运单,这个就会造成重复支付的可能,所以我们首先需要将每次请求中的运单 id 记录下来,存储到 redis 或者数据库,这样在 MQ 发起支付时,判断下每笔运单的状态,如果是处理中,则直接跳过,不再处理。目前我主要犹豫不定的是把这 1000 笔运单的 id 存储到 redis 中还是数据库中。
wuyiccc
39 天前
状态补充一个处理中的中间状态,提交的这 1000 单修改状态为处理中,等后续异步处理完成之后再修改为处理完成,并发问题给记录加一个 version 字段,并发更新的时候判断版本号是否相等
yc8332
39 天前
其实你现在不就是异步支付吗?发起支付后应该不用再人工参与了吧?如果是这样直接批量更新成支付中,可以分布式锁再加个标志保险一点。接下来就和用户无关了,他也只能发起其他的未支付订单
loszhang
39 天前
@wuyiccc 就是在用户发起这 1000 笔运单支付请求是,我要异步记录 1000 笔运单的处理中状态,还是同步记录,如果是异步记录,直接返回给用户处理中的结果,这样用户查到的可能还有没来及的记录处理中状态的运单。如果同步去记录这 1000 笔运单,需要的时间会长些,会让用户在界面有个等待的时间。
loszhang
39 天前
@yc8332 对,发起后就不需要用户再参与了,等待最后的处理结果就行,失败或者成功都会记录到运单状态中。
lsk569937453
39 天前
@loszhang 肯定是异步记录。用户发起 1000 笔运单支付请求后,前端直接展示"运单支付处理中,完成后将会发送短信通知,在此期间请不要重新提交新的运单支付。"就完事了。

在用户的 1000 笔运单处理过程中,不允许用户再次提交另外的 1000 笔运单支付。这样是最简单的。
None2
39 天前
「要异步记录 1000 笔运单的处理中状态,还是同步记录?」

运单状态同步更改为 [处理中] ,异步做其他逻辑,异步处理完成后,状态再更改为 [已处理]
yc8332
39 天前
@loszhang 那就是我发的那个流程就能走通了。对于有并发去做相同操作的记得加锁就行
wuyiccc
39 天前
@loszhang 同步只修改 1000 单运单的支付状态为支付中,后面其他操作都改为异步操作,前面的这个只修改支付状态的处理逻辑也会很慢么?
yc8332
39 天前
@loszhang 如果要给前端更好的体验,可以说支付完成了昨天异步拉取或者说推送结果
iOCZS
39 天前
那就前端轮询嘛,完成后刷新页面
loszhang
39 天前
@lsk569937453 因为用户的运单量比较大,且支付时间集中,基本就是月底,大概 6 万以上,如果用户发起一次请求,直到运单全部处理完成之前不允许再支付,这个是不行的。
loszhang
39 天前
@None2 如果是同步更改运单处理中的状态,我试下了,我是重新建了一张表,有个 id 主键字段,一个运单 id 字段,1000 条数据,我是循环插入,用了 40 秒。
loszhang
39 天前
@yc8332 支付是使用异步处理。现在我犹豫不决的是发起支付请求如何去记录运单支付处理中的状态,因为有 1000 笔运单,我要同步去修改,耗时较长,如果把这部分也做成异步处理,用户刷新到运单数据,可能会有上次请求中还未修改状态的运单。
loszhang
39 天前
@wuyiccc 我试下了循环插入 1000 条数据,40 秒。我再换下其他插入的方式。我们使用的是 mybatis.
loszhang
39 天前
@iOCZS 我们可以先给前端一个处理中的结果,后续的支付都是异步,前端刷新就可以看到最新结果。
perbugwei
39 天前
mybatis 的 savebatch 那个方法?那个方法不能处理数据量大的情况,但是 1000 条数据也不会 40s ,是不是别的逻辑的问题。
loszhang
39 天前
@perbugwei 不是 savebatch ,就是 insertSelective
dong568789
39 天前
客户发起运单支付,这些运单不是应该先更新状态(除理中),后续是不是就查不到了,也不会有重复提交的问题

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

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

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

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

© 2021 V2EX