如何与第三方接口保持数据一致性
大家经常遇到这样的需求,尤其是支付中心接口的时候:
查询满足某种条件的订单,调用第三方接口成功,更改订单状态。
常见实现示例
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
    我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他
们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其
实我是一个程序员
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号