V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
liuawei
V2EX  ›  程序员

大量支付订单轮询,各位有什么好的方法解决。

  •  1
     
  •   liuawei · 2019-03-15 11:16:02 +08:00 · 8335 次点击
    这是一个创建于 2062 天前的主题,其中的信息可能已经有所发展或是发生改变。
    声明一下领导给的时间在 3 个工作日完成任务,接入的支付方式比较多,微信(扫码,H5,小程序)、支付宝(扫码,H5,刷脸),收钱吧,威富通等。
    使用的是 Java 语言。目前 1 分钟差不多高峰有 300 单。目标是能支持一分钟 600 单。
    44 条回复    2019-10-28 23:52:59 +08:00
    liuawei
        1
    liuawei  
    OP
       2019-03-15 11:19:24 +08:00
    说明一下:300 单是有效订单,已经支付订单,参与轮询的订单大概是有效单的两倍。
    Raymon111111
        2
    Raymon111111  
       2019-03-15 11:22:11 +08:00
    啥叫轮询

    1 秒 10 单基本不用太考虑性能
    Vegetable
        3
    Vegetable  
       2019-03-15 11:26:05 +08:00
    是看订单有没有支付完成?
    你们不是用回调的吗?再说清楚一点吧
    Moker
        4
    Moker  
       2019-03-15 11:26:52 +08:00
    4 方支付?
    PhpBestRubbish
        5
    PhpBestRubbish  
       2019-03-15 11:27:59 +08:00
    支付不是有回调吗,要轮询干嘛?
    1sbugou
        6
    1sbugou  
       2019-03-15 11:30:57 +08:00
    威富通。。呵呵
    liuawei
        7
    liuawei  
    OP
       2019-03-15 11:32:19 +08:00
    @Raymon111111 就是查询订单支付状态。有的时候一次支付查询请求都需要 1 秒哦。
    liuawei
        8
    liuawei  
    OP
       2019-03-15 11:33:02 +08:00
    @Moker 公司是做自助售卖机的,所以细分的支付方式有 10 几种。
    Mrun
        9
    Mrun  
       2019-03-15 11:35:20 +08:00
    AMQ
    Moker
        10
    Moker  
       2019-03-15 11:35:21 +08:00
    订单状态对方有回调 等通知就好了 主动查询只是一个补偿 量很小 加上异步去请求就可以了
    liuawei
        11
    liuawei  
    OP
       2019-03-15 11:35:33 +08:00
    @Vegetable 第一个轮询会存在网络节点丢单情况,第二个比如支付宝反扫,刷脸支付会没有回调,会存在请求支付宝接口,支付宝接口 Socket 异常,我们这边异常,支付宝已经扣款成功。

    还有例如威富通这种机构有的时候回调会有问题。
    arrow8899
        12
    arrow8899  
       2019-03-15 11:36:46 +08:00
    消息队列,设置多个线程同时消费,你开 20 个线程,查一次 1s,1 分钟也有 1200 单了
    liuawei
        13
    liuawei  
    OP
       2019-03-15 11:36:55 +08:00
    @1sbugou 威富通遇到过一次不进行回调,还有就是关闭支付通道这种骚操作。
    skymei
        14
    skymei  
       2019-03-15 11:38:16 +08:00
    不同的支付类型放到不同的队列,开线程去对应的队列,1 分钟 600 单不算很大的量,应该是处理的过来.看你们的服务器配置以及代码部署方式了,要是有负载均衡,缓存的话基本不用担心。
    liuawei
        15
    liuawei  
    OP
       2019-03-15 11:38:43 +08:00
    @Moker @arrow8899 消息队列考虑过,但是时间短,假如队列要改至少三个项目,H5,小程序,原生这些都是不同的项目。
    1sbugou
        16
    1sbugou  
       2019-03-15 11:39:28 +08:00
    @liuawei 威富通比较坑,毕竟它是自成一体的通道,不像其他银行和三方
    kingOfWorLd
        17
    kingOfWorLd  
       2019-03-15 11:43:12 +08:00
    其实可以用消息队列的,每次支付成功,如果有回调成功了,就返回成功,如果没有回调,需要主动查询的,就抛到消息队列中,如果消息队列查询成功,更新订单状态,如果查询失败,再接着抛进消息队列,记录查询失败的次数,如果失败次数大于 5 次,那么就要进入反馈系统了,人工去查询,干预。
    liuawei
        18
    liuawei  
    OP
       2019-03-15 11:45:18 +08:00
    @kingOfWorLd 说了只有三个工作日,原生支付,H5, 小程序是不同的项目都要改,公司以前没有用过消息队列。
    liuawei
        19
    liuawei  
    OP
       2019-03-15 11:48:43 +08:00
    目前自己的解决方案是,JOB 轮询,每种支付方式建立一个任务。 但是我们领导说也会存在丢单的情况,他的观念说,查询请求 0.5S+我们业务逻辑处理,下货 0.5S 。一分钟超过 100 单的话会存在有些订单轮询不到。
    mortonnex
        20
    mortonnex  
       2019-03-15 11:50:10 +08:00
    楼主怕不是对轮询有什么误解
    kingOfWorLd
        21
    kingOfWorLd  
       2019-03-15 11:59:30 +08:00   ❤️ 1
    @liuawei 简单点用用 redis 的消息队列,专业一点用 rabbitMq,其实就是一个环境搭建,很容易学习的,这个叫做方法正确性,美团等一些公司都是这个思路,关于时间问题,我觉得 3 个小时足够你学习了,如果你不去建立分布式消息队列集群(可能现阶段你也不需要),说白了,简单的就是 socket 连接,读者写者的模型啊。
    no1xsyzy
        22
    no1xsyzy  
       2019-03-15 12:27:08 +08:00
    我猜问题是单线程阻塞式轮询,多线程或者非阻塞再垃圾也是 1000/s 以上的查询量(以优化垃圾的 CPython 为例)
    猜错就当我没说
    no1xsyzy
        23
    no1xsyzy  
       2019-03-15 12:29:38 +08:00   ❤️ 1
    添加“我已付款完成”按钮,由用户通知你去查询?
    Asice
        24
    Asice  
       2019-03-15 12:38:16 +08:00
    多线程并发过去查询,一分钟 1w 单都轻轻松松,反正性能也在被查方,简单粗暴时间快
    liuawei
        25
    liuawei  
    OP
       2019-03-15 12:50:13 +08:00
    @kingOfWorLd 恩恩核心我知道下单模块写入订单,轮询模块处理订单。只是只有三天时间,还有你说的 Rabbitmq 和 redis 都比较熟悉,我还是去跟领导多申请几天时间。
    heypig
        26
    heypig  
       2019-03-15 13:34:37 +08:00
    跑个题 , 乱扯两点.

    1. 方案根治要还是靠 支付的 callback. 主动 query 的只是在 callback 的异常下补偿. 因为 callback 不完全可靠就放弃 callback, 这是因噎废食. callback+query 补偿. 才合理解决.
    关于轮询的实现, 看你们自己的技术体系实现了(自己系分去)

    2. 提醒一下, query 有两个常见的误区.
    a. query 没找到单据, 当做"失败"处理. 其实不一定, 又可能下游处理慢未下单, 所以一般有个业务约定的超时时间, 只有超时时间真正超出了, 才是真的失败.
    b. 如果允许一笔订单多次支付, 对多余的支付单要及时退款, 否则你又坑用户了; 实现层面, 比对一下之前支付单号.
    以上两点, 支付类业务还好, 细节不当, 你坑了用户, 多付没退 ; 提现类业务, 可能多提钱出去了, 公司要亏.

    --------------
    这类场景 case 很典型很常见, mark 一下. 有空写点总结说说

    ---------------

    ps. 专业做支付,来蚂蚁. 广告小尾巴, 谢谢
    https://www.v2ex.com/t/541340
    rockyou12
        27
    rockyou12  
       2019-03-15 14:33:02 +08:00
    lz 考虑有问题,支付成功不回调是个小概率事件。实际情况你只要查询超时订单是否支付就行了。

    比如订单有一分钟的窗口,一分钟后(不需要很准确,一个 10s,20s 的定时器轮询查都可以)再主动查询支付平台,如果没支付就关闭订单。

    如果网络等出现严重问题,客户多次支付,你只要业务上能回算出用户多付的钱,事后走渠道退回,其实也不会是很严重的问题。
    sujin190
        28
    sujin190  
       2019-03-15 14:42:37 +08:00
    支付宝和微信都有延时重试策略,几乎不会出现挂的情况,其他的支付方式可能通知不是很严谨,但是用户量小的话几乎可以忽略了吧,能用就是了,三天就搞出来的还想咋滴了
    x7395759
        29
    x7395759  
       2019-03-15 14:44:37 +08:00
    所以横向扩容一个系统,不就从 300 变成 600 了,然后就花多一些时间写新的容量更大的系统。依照我的理解你现在似乎无法完成这个工作,所以需要花大于 3 天的时间。
    ysweics
        30
    ysweics  
       2019-03-15 15:04:29 +08:00
    感觉楼主需要一个应急的方案,如果只是应急的方案,你自己方案也可以,但是如果要保持系统的良好,那队列必不可少,就看你和你领导怎么权衡了
    liuawei
        31
    liuawei  
    OP
       2019-03-15 15:18:44 +08:00
    @rockyou12 我们是做 SASS 服务,前几天遇到几笔丢单,然后用户说支付没有下货,就投诉到我们客户那里,让后客户就说我们“吃”单。所以就不打算和我们合作了。
    rockyou12
        32
    rockyou12  
       2019-03-15 15:56:26 +08:00
    @liuawei 但光看你这个说法也不清楚问题在不在支付那块啊……
    yc8332
        33
    yc8332  
       2019-03-15 16:37:42 +08:00
    订单量很少啊。。。订单放队列里,开 N 个线程去跑就好了,订单多就多开几个。。过期就关掉订单。。
    ghos
        34
    ghos  
       2019-03-15 18:01:10 +08:00
    老实讲你的队列不用 redis mq 也可以 用 blockingqueue 都行 只要做好队列内容持久化就好了
    limuyan44
        35
    limuyan44  
       2019-03-15 20:13:48 +08:00 via Android
    你看目前一分钟可以支持 300,我们花一分钟向老板申请一台机器就变成 600 啦。。至于改造我们以后慢慢来吗
    kaneg
        36
    kaneg  
       2019-03-15 21:40:51 +08:00 via iPhone
    如果来不及引入新的组建( MQ 之类),就用数据库模拟队列,用不同的标记位来维护状态,定时查询指定状态的数据记录,然后扔到线程池去异步处理。只要处理速度快于订单的到来速度就没啥问题。如果处理不过来,就根据瓶颈在 CPU 还是内存来增加相应的资源。
    MeteorCat
        37
    MeteorCat  
       2019-03-15 21:47:09 +08:00 via Android
    是不是搞支付超时回调,马个鸡,好多第三方支付回调轮询好不靠谱,接入一次天天订单异常
    runningman
        38
    runningman  
       2019-03-16 07:58:22 +08:00 via iPhone   ❤️ 1
    @liuawei 我也做自动售货机 可以微信交流 270115861
    runningman
        39
    runningman  
       2019-03-16 08:19:27 +08:00 via iPhone
    哈哈 这些 case 我之前就这么实现的
    sinboy1988
        40
    sinboy1988  
       2019-03-16 11:00:50 +08:00
    @kingOfWorLd 没有回调是什么意思,不太明白
    guijianshi01
        41
    guijianshi01  
       2019-03-16 16:46:02 +08:00
    回调,别做轮询,加上延时队列做超时处理就好了
    troywinter
        42
    troywinter  
       2019-03-16 19:39:26 +08:00
    回调加超时轮询,另外,轮询必然不能本地同步做啊,先多线程再加分布式。。。
    liuawei
        43
    liuawei  
    OP
       2019-10-25 17:56:29 +08:00
    @runningman 刚看到 这微信搜索不到呀
    runningman
        44
    runningman  
       2019-10-28 23:52:59 +08:00 via Android
    @liuawei 可以啊 270115861 或者 zhtsuc
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3026 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:31 · PVG 22:31 · LAX 06:31 · JFK 09:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.