1
wolfan 224 天前 1
前端给个加载打印的,就一行一行打印成交信伪装成处理,后台分批提交 6W 单不就好了。
|
2
loszhang OP @wolfan 我们现在的方案是,前端发起请求后,后端直接返回类似交易已受理的结果,前端不用再等待后端对这笔请求中 1000 笔运单的一个预处理(修改运单状态及相关表),因为这个太耗时,所以我们后端接收到这 1000 笔运单后,先记录下 1000 笔运单的 id ,异步去处理,但是在这处理这笔运单时,客户还会继续发起下一次 1000 笔运单的支付请求,这个 1000 笔运单中,肯定会有上次请求还未来得及修改运单状态的运单,这个就会造成重复支付的可能,所以我们首先需要将每次请求中的运单 id 记录下来,存储到 redis 或者数据库,这样在 MQ 发起支付时,判断下每笔运单的状态,如果是处理中,则直接跳过,不再处理。目前我主要犹豫不定的是把这 1000 笔运单的 id 存储到 redis 中还是数据库中。
|
3
wuyiccc 224 天前
状态补充一个处理中的中间状态,提交的这 1000 单修改状态为处理中,等后续异步处理完成之后再修改为处理完成,并发问题给记录加一个 version 字段,并发更新的时候判断版本号是否相等
|
4
yc8332 224 天前
其实你现在不就是异步支付吗?发起支付后应该不用再人工参与了吧?如果是这样直接批量更新成支付中,可以分布式锁再加个标志保险一点。接下来就和用户无关了,他也只能发起其他的未支付订单
|
5
loszhang OP @wuyiccc 就是在用户发起这 1000 笔运单支付请求是,我要异步记录 1000 笔运单的处理中状态,还是同步记录,如果是异步记录,直接返回给用户处理中的结果,这样用户查到的可能还有没来及的记录处理中状态的运单。如果同步去记录这 1000 笔运单,需要的时间会长些,会让用户在界面有个等待的时间。
|
7
lsk569937453 224 天前
@loszhang 肯定是异步记录。用户发起 1000 笔运单支付请求后,前端直接展示"运单支付处理中,完成后将会发送短信通知,在此期间请不要重新提交新的运单支付。"就完事了。
在用户的 1000 笔运单处理过程中,不允许用户再次提交另外的 1000 笔运单支付。这样是最简单的。 |
8
None2 224 天前
「要异步记录 1000 笔运单的处理中状态,还是同步记录?」
运单状态同步更改为 [处理中] ,异步做其他逻辑,异步处理完成后,状态再更改为 [已处理] |
12
iOCZS 224 天前
那就前端轮询嘛,完成后刷新页面
|
13
loszhang OP @lsk569937453 因为用户的运单量比较大,且支付时间集中,基本就是月底,大概 6 万以上,如果用户发起一次请求,直到运单全部处理完成之前不允许再支付,这个是不行的。
|
14
loszhang OP @None2 如果是同步更改运单处理中的状态,我试下了,我是重新建了一张表,有个 id 主键字段,一个运单 id 字段,1000 条数据,我是循环插入,用了 40 秒。
|
15
loszhang OP @yc8332 支付是使用异步处理。现在我犹豫不决的是发起支付请求如何去记录运单支付处理中的状态,因为有 1000 笔运单,我要同步去修改,耗时较长,如果把这部分也做成异步处理,用户刷新到运单数据,可能会有上次请求中还未修改状态的运单。
|
18
perbugwei 224 天前
mybatis 的 savebatch 那个方法?那个方法不能处理数据量大的情况,但是 1000 条数据也不会 40s ,是不是别的逻辑的问题。
|
20
dong568789 224 天前
客户发起运单支付,这些运单不是应该先更新状态(除理中),后续是不是就查不到了,也不会有重复提交的问题
|
21
loszhang OP @dong568789 如果是同步更新状态,就不会出现用户会重复提交的问题。如果是异步更新状态,就会出现。
|
22
ftsland 224 天前
楼主的需求 redis 挺合适的啊, 根据客户 id 记录到 set 里, 你是怕 redis 的数据意外挂了没了吧, 同时把运单数据记录到日志里呗
|
23
loszhang OP @perbugwei 我换成 foreach 插入,1000 笔,300 毫秒。那我就同步记录下请求中的运单 id ,查询时过滤掉已经记录的运单,这样就不会再重复发起。
|
24
offswitch 224 天前
6w id 也不是很多,1000 笔订单,作为一次批处理,用户支付一次,记录这 1000 笔订单的 id ,甚至都不用逐个修改状态,如果重复提交已处理的订单 id ,后台直接抛出错误。
前端设计上,考虑一下新开一个批量处理订单,这几万个订单一次性返回,一页展示 1000 行,这一页处理完成,前端过滤掉这一页,显示下一页。 |
25
offswitch 224 天前
至于后面的修改订单状态,放到 mq 中一个个修改成处理中,之后订单一个个入队,走正常订单处理流程
|
26
offswitch 224 天前
前端页面展示状态,后端你可以直接从 redis 中取订单的状态(批量提交的订单 id 一定要记录到数据库里面),如果有这个订单 id ,说明订单正在处理中,不用实际修改数据库中每一个订单的状态
|
27
loszhang OP @offswitch 我主要是一开始不太确定,应该如何去更改这 1000 笔运单的状态,如果同步修改,可能会耗时比较久,给用户的感受不太好。我刚才换了中批量插入的方式,很快了。
让前端设计下,这个一般前端是不太想参与的,😄。 |
28
loszhang OP 感谢大家的回复,我目前选择的方式是,用户发起批量支付时,同步将运单的 id 写入新表中,然后返给前端处理中的结果。前端查询时,我会过滤掉已经记录的运单,这样就不会造成用户重复发起。
因为一开始我担心批量修改和插入会比较耗时,我试下了循环调用 insert 插入,确实比较费时,1000 条 40 秒,然后换成 foreach 插入,1000 条 300 毫秒。所以选择同步去记录运单。 后续如果还有其他问题,也会更新,感谢。 |
29
Satella 224 天前
你们这个客户,应该是做网络货运的吧,说不定还带点违规那种
|
30
lanfeng579 224 天前
@loszhang #28 你这个肯定不能循环 insert 啊 你循环插入 网络 IO 次数太多了,建议是接口进入的时候 你就去加分布式锁,不然的话 会有并发问题,撞上了同时点的快点,可能你还没存进去 他又发起了支付请求,这种 最好多测一下
|
31
zhkn 224 天前 via iPhone
循环调用 insert1000 次也不应该是 40 秒吧,循环中还做了其他处理吗
|
32
Jack66 224 天前
mq 处理没问题,注意数据一致性问题。好奇的是你们怎么自动支付,支付有这种功能吗,即使有的话,支付应该提供 api 批量支付,然后响应参数。
|