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

mac2022-06-30  191

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

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

常见实现示例

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();                }

  

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

往两个方面思考

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

方案

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

转载于:https://www.cnblogs.com/kms1989/p/5620950.html

相关资源:JAVA上百实例源码以及开源项目

最新回复(0)