• 如何与第三方接口保持数据一致性


    大家经常遇到这样的需求,尤其是支付中心接口的时候:

    查询满足某种条件的订单,调用第三方接口成功,更改订单状态。

    常见实现示例

    task1:

    orders = queyrOrder(...); //查询已离店的订单
            for (Map<String, Object> order : orders) {
                try {
                    con.setAutoCommit(false);
     
                    String orderNo = (String) order.get("order_no");
     
                    // 调用支付中心返现接口
                    callCommission(order);  //无论是网络异常还是返回结果失败,都抛异常
                    // 更改订单状态
                    cashedOrder(con, order); //更改订单状态
     
                    con.commit();
            }

      

    task 2 

    orders = queyrOrder(...);//查询“返现中”的订单
     
     for (Map<String, Object> order : orders) {
     
            con.setAutoCommit(false);
            // 调用返现任务
            callCommission(order);
     
            // 更改订单状态
            cashedOrder(con, order);
     
            con.commit();           
     
     }

      

    示例的问题
    1. 在事务中存在远程调用,容易导致事务时间过长
    2. 在callCommission 和 cashedOrder之间,是否有其他操作能改变该订单状态? 如果有,是否会出现多次调用第三方的问题?
    3. 第三方接口特性未知
    设计方案

    往两个方面思考

    1. 自己系统本身数据一致性
    2. 如果调用第三方接口 和 更新自己系统数据 之间任何一个环节 出异常了。比如:应用重启,机房网络问题等。如何保证第三方接口和自己系统的数据一致性?

    方案

    1. 加锁,方案有:版本号乐观锁、select for update 悲观锁。
      延伸问题:在原表上执行task,还是队列表?
    2. 第三方接口需要什么特性才能保证数据一致性? 要考虑网络超时问题、应用发布重启、并发等问题。
    • 回调
    • 提供结果查询
    • 幂等性
    重构后的示例1:

    (幂等接口的方案)

    
    
    queueOrders = queryQueueOrders();
    for(QueueOrder order : queueOrders){
       callApi()
       startTransaction();
       lock(order);  
       updateStatus()
       commitTransaction();
    }
    
    

    (提供结果查询的API接口的方案)

    
    
    queueOrders = queryQueueOrders();
    for(QueueOrder order : queueOrders){
       try{
          startTransaction();
          if(isBeingProcess(order)){
              Result r = queryAPIResult();
              if(r.success()){
                return;
              }
          }
          lock(order);
          callApi()
          updateStatus();
       }finally{
       commitTransaction();
       }
    }
    
    

    注意:该示例依然有“在事务中调用远程接口的问题”

    http://www.cnblogs.com/NanguoCoffee/archive/2013/03/30/2990918.html

    我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他 们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其 实我是一个程序员
  • 相关阅读:
    [JavaScript]继续学习DOM事件模型
    [面试]作答整理一些面试题
    [JavaScript]使用jQuery实现无缝轮播
    [JavaScript]使用CSS + jQuery 实现自动轮播图
    [JavaScript]从DOM到jQuery(2)
    [JavaScript]从DOM到jQuery(1)
    [JavaScript]JavaScript中的函数(2)
    [JavaScript]JavaScript中的函数(1)
    [JavaScript]JavaScript中的Array
    React练习 7 :点击div,显示innerHTML
  • 原文地址:https://www.cnblogs.com/kms1989/p/5620950.html
Copyright © 2020-2023  润新知