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

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

  •  2
     
  •   liuawei · 10 天前 · 2962 次点击
    声明一下领导给的时间在 3 个工作日完成任务,接入的支付方式比较多,微信(扫码,H5,小程序)、支付宝(扫码,H5,刷脸),收钱吧,威富通等。
    使用的是 Java 语言。目前 1 分钟差不多高峰有 300 单。目标是能支持一分钟 600 单。
    42 回复  |  直到 2019-03-16 19:39:26 +08:00
        1
    liuawei   10 天前
    说明一下:300 单是有效订单,已经支付订单,参与轮询的订单大概是有效单的两倍。
        2
    Raymon111111   10 天前
    啥叫轮询

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

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

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

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

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

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

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

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

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