网络延迟导致供货商结算多次支付——方案优化

  发现有网友对网络延迟导致供货商结算多次支付这篇文章提出问题:多个用户同时支付多个采购订单的话,是不是会阻塞在那里?

  答案是一定会的,并且这个事务涉及到微信支付网络调用,事务时间比较长。下面讲解一种优化方案,讲解之前先说明《阿里巴巴Java开发手册_v1.4.0》对加锁的开发原则。

6. 【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁; 能锁区块,就不要锁整个方法体; 能用对象锁,就不要用类锁。
说明: 尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用 RPC 方法

                          ——参考《阿里巴巴Java开发手册_v1.4.0》
  上一篇在整个方法块上加锁,而且在锁代码块中调用 RPC 方法,违背了开发设计的原则。该如何优化呢?
  我们重新分析下后端支付的简化逻辑:
              在这里插入图片描述
  如果在第一步汇集采购记录加锁,满足设计原则,但无法解决问题。原因是虽然线程异步获取采购记录的数据,但会生成不同的支付记录再去调用微信支付,之后在修改采购记录状态时发生数据库操作异常。
  上述整个过程中,并不是所有步骤都需要满足ACID,只有第一步汇集采购记录和最后一步修改采购记录状态时才需要,因而我们调换下顺序,汇集采购记录和修改采购记录的状态放到一起,并且对这个代码块加锁,满足《阿里巴巴Java开发手册》,能很好的提高并发性。

    @Override
    public Message payment(List<Purchase> list, Admin admin) {
        PurchaseOrder purchaseOrder;
        synchronized (this) {
            purchaseOrder = create(list, admin);
            // 标记采购记录结算成功
            for (Purchase purchase : list) {
                purchase.setStatus(PurchaseOrderStatus.completed);
            }
        }
        if (null == purchaseOrder) {
            return new Message(Message.Type.error, "请选择同一个供货商,且状态为等待主管审核或会计审核通过!");
        }
        ...

  简单分析下上述方法的过程:
  1、两个线程同时执行到汇集采购数据(只有等待支付状态的数据),由于这个地方有锁,因而只有一个线程进入,并且修改了采购数据的状态,继续执行其他方法;
  2、第二个线程进入代码块,无法得到汇集的采购数据直接返回。

知识点
1、《阿里巴巴Java开发手册_v1.4.0》
2、事务的ACID原则与CAP原理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值