一天大概会生成七八千量的订单数据,逐一去调用第三方支付接口支付。已有逻辑是使用定时任务同步执行的,每 5 秒执行一次,需要执行几个小时才能完成。怎么改造一下能快速处理完? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
typ1805
V2EX    问与答

一天大概会生成七八千量的订单数据,逐一去调用第三方支付接口支付。已有逻辑是使用定时任务同步执行的,每 5 秒执行一次,需要执行几个小时才能完成。怎么改造一下能快速处理完?

  •  
  •   typ1805 2021-04-02 13:55:42 +08:00 4298 次点击
    这是一个创建于 1701 天前的主题,其中的信息可能已经有所发展或是发生改变。
    42 条回复    2021-04-03 14:16:49 +08:00
    KouShuiYu
        1
    KouShuiYu  
       2021-04-02 14:16:43 +08:00
    改成多个请求接力执行
    KouShuiYu
        2
    KouShuiYu  
       2021-04-02 14:20:27 +08:00
    之前写过一个多文件上传,设置好最大同时上传的数量,每当有一个上传完成自动开启下一个上传任务
    wantooo
        3
    wantooo  
       2021-04-02 14:25:33 +08:00
    对方的支付接口很耗时吗,你 iob 拉起来发给多个线程执行呗
    rylei
        4
    rylei  
       2021-04-02 14:25:56 +08:00
    这种用消息队列生成之后直接调支付不好吗?
    ch2
        5
    ch2  
       2021-04-02 14:29:10 +08:00 via iPhone
    Python 用 grequests,一口气支付 1000 个订单,当然只要你胆子大就可以
    typ1805
        6
    typ1805  
    OP
       2021-04-02 14:31:46 +08:00
    @ch2 用的是 Java
    typ1805
        7
    typ1805  
    OP
       2021-04-02 14:32:19 +08:00
    @rylei 嗯嗯,想着是用消息队列
    Dimomo
        8
    Dimomo  
       2021-04-02 14:32:54 +08:00
    并发请求不行吗?
    typ1805
        9
    typ1805  
    OP
       2021-04-02 14:33:23 +08:00
    @wantooo 调用的三方支付比较多,有的比较耗时
    ch2
        10
    ch2  
       2021-04-02 14:34:44 +08:00 via iPhone
    @typ1805 java 应该也有对应的网络库,批量发送请求的那种,不用一个一个等
    qiayue
        11
    qiayue  
    PRO
       2021-04-02 14:34:54 +08:00
    先看执行一次请求需要耗时多久,一般 200 毫秒内,那么 1 秒钟就可以请求 5 次。
    实际上你 1 秒钟可以请求超过 5 次,只要对方没有限制。

    最好的办法然是,用队列。
    如果还想用定时任务,那么可以改为 1 秒一次,然后每次取 5 条订单出来,同时发 5 个请求,或者发一个请求,等返回结果后再发下一个请求。

    注意要防止重入,举例第一次你取出来 5 条是 1,2,3,4,5,结果你程序处理到第 4 条时,下一秒又被取出来 5 条是 5,6,7,8,9,那么 5 就有可能被对方处理 2 次。
    keepeye
        12
    keepeye  
       2021-04-02 14:39:40 +08:00
    用 go 就很好解决了。其他也可以用队列+多进程方式处理
    eason1874
        13
    eason1874  
       2021-04-02 14:41:46 +08:00
    看对方 API 频率限制,按 90%最大并发去提交请求,再慢也没办法了。
    whileFalse
        14
    whileFalse  
       2021-04-02 14:44:26 +08:00
    为啥要攒起来逐一调用?请求来了实时调用不行吗?
    Kilerd
        15
    Kilerd  
       2021-04-02 14:48:30 +08:00
    如果对方没有 API 调用限制,异步一梭子,分分钟搞定。
    typ1805
        16
    typ1805  
    OP
       2021-04-02 14:50:12 +08:00
    @whileFalse 业务是批量导入数据,系统自动生产订单入库(状态为未支付),再从数据库读取数据进行支付,更新状态。
    typ1805
        17
    typ1805  
    OP
       2021-04-02 14:50:51 +08:00
    @qiayue 感谢,打算用队列干
    sarices
        18
    sarices  
       2021-04-02 14:53:10 +08:00
    为何不并发去处理呢,数据导到队列,并发几个去处理
    Jooooooooo
        19
    Jooooooooo  
       2021-04-02 14:56:17 +08:00
    并发的搞啊, 不同订单是独立的.
    zw1one
        20
    zw1one  
       2021-04-02 14:57:03 +08:00
    每 5 秒执行一次,一次执行一条数据?
    WangRicky
        21
    WangRicky  
       2021-04-02 14:59:36 +08:00   1
    分通道多个任务去处理,比如按照订单最后一位,那么就会提升 10 倍,或者对订单取模型,分割的方法有很多,这样不用引入新的中间件,而且对数据的进度,成功情况有更好的掌握
    hxndg
        22
    hxndg  
       2021-04-02 15:01:59 +08:00
    典型的批处理任务?
    fiypig
        23
    fiypig  
       2021-04-02 16:02:34 +08:00
    推荐用 Go
    AngryPanda
        24
    AngryPanda  
       2021-04-02 16:03:49 +08:00
    这种支付过程是不需要用户参与的吗?
    daimameiwenti
        25
    daimameiwenti  
       2021-04-02 16:17:10 +08:00
    你用 queue 队列处理订单,一个个处理,OK 的就移除队列,不 OK 的就继续 offer
    zw1one
        26
    zw1one  
       2021-04-02 16:18:55 +08:00
    1 、如果你要改动小的话,就在处理的地方加个线程池,多设置几个线程同时做支付发送就好了,注意 oom 问题。
    2 、如果要改一改架构,上个 mq 提升系统可用性的话,我大概设计了个架构。
    https://www.processon.com/view/link/6066cde95653bb5ceafdc638
    wsbnd9
        27
    wsbnd9  
       2021-04-02 16:40:13 +08:00
    串行 变成 并行调度 跟语言就没啥关系了
    tcsky
        28
    tcsky  
       2021-04-02 16:56:53 +08:00
    你这个不是常规支付接入吧, 是客户下单后用自己账号代付么?多准备几个账号
    Masonnn
        29
    Masonnn  
       2021-04-02 17:34:43 +08:00
    @zw1one #26 牛逼啊 [赞]
    cpstar
        30
    cpstar  
       2021-04-02 17:40:45 +08:00
    为什么不说说为什么已有逻辑设定 5 秒钟搞一次,
    5*8000=40000/3600=11.111 ,那必然半天都在处理订单了。
    我只想知道当初是哪个~哔~设计的这个逻辑。
    cpstar
        31
    cpstar  
       2021-04-02 17:41:41 +08:00
    换句话讲,能保证每一个单子 5 秒钟能处理完?如果没有处理完的,下一个单子怎么办?
    这特么没学过边界测试吧。。。
    corningsun
        32
    corningsun  
       2021-04-02 18:31:39 +08:00
    用阻塞队列就好啦
    一个线程捞任务到队列,如果队列满了就等待
    再搞一个消费线程池,直接从队列取,队列满了就等待。(需要控制消费线程池的大小,保证不把支付接口压垮就好)
    corningsun
        33
    corningsun  
       2021-04-02 18:33:34 +08:00
    修正下:再搞一个消费线程池,直接从队列取,队列空了就等待
    arvinsilm
        34
    arvinsilm  
       2021-04-02 20:08:33 +08:00
    定时任务一般是一次取出全部未执行的数据去执行,没有未执行的数据则等待下次执行。不是每次只取一条数据。。。。。
    pcbl
        35
    pcbl  
       2021-04-02 20:28:37 +08:00 via Android
    平均 10 秒一个新订单,5 秒去执行一次,可以接受,既不会大量积压也不会频繁请求
    pcbl
        36
    pcbl  
       2021-04-02 20:33:32 +08:00 via Android
    不更改原有逻辑不增加中间功能的情况下可以把 5 秒改成一秒,每间隔一秒钟就去获取一个最早生成的未处理的订单,添加一个处理中标记,执行完成后标记为已处理
    dzdh
        37
    dzdh  
       2021-04-02 20:37:33 +08:00
    @typ1805 java 不是有 threadpool 么。
    stardust21
        38
    stardust21  
       2021-04-02 21:05:28 +08:00
    Java 的话直接用固定数量的线程池解决?
    tjq
        39
    tjq  
       2021-04-02 22:38:02 +08:00 via iPhone
    可以试试 PowerJob 这个任务调度框架,支持 MapReduce 分布式计算,很符合你的场景。
    hahasong
        40
    hahasong  
       2021-04-03 00:14:34 +08:00
    开个 threadpool 不就行了 试出 api 的极限 设置一个 80%的大小
    typ1805
        41
    typ1805  
    OP
       2021-04-03 14:16:19 +08:00
    @zw1one 感谢
    typ1805
        42
    typ1805  
    OP
       2021-04-03 14:16:49 +08:00
    @tjq 感谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     853 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 20:37 PVG 04:37 LAX 12:37 JFK 15:37
    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