首页 > 代码库 > 【原】关于定时回查出现的BUG有感

【原】关于定时回查出现的BUG有感

   前言:今天有同事反映说客户在平台投标后,看到的是失败状态,但是钱在某银行的状态是被冻结了,我这边给出答复是只有投标成功才会冻结。

     首先写下流程:P2P对接某银行托管,某银行的部分接口要求我们通过同步回查的方式对订单再次确认,投标是其中一个。我们这边P2P后台是5分钟查询一次金额订单表,把处理中和待处理的订单拿出来组装报文加密上送到X银行,然后根据返回数据确认是否ok?如果失败那么这笔订单关联的操作也是失败,成功则反之。

   为什么需要回查呢?

  •  用户在某银行操作的时候如果超过25分钟就是失败,但25分钟内都属于处理中,需要空5分钟确认期间的状态。
  •    可能是某银行考虑到消息一致性问题,所以需要我们再请求一次确认订单,当然时间也是5分钟后。

   恰巧的是今天才发现这个bug,而且是很严重的bug。因为我再次确认订单的时候,发现ctime和utime相隔1秒,但是很奇怪的用户操作哪有这么快1秒就完成了操作。再后来看到订单创建时间是12:15分,马上想起我们平台定时回查是5分钟一次,刚好满足定时任务,也就是用户刚好12:15创建了一笔订单是待处理,还没跳到某银行页面,就被我们后台定时任务扫描去了某银行,某银行返报文没有该订单,然后悲剧来了,用户高兴的投了一笔钱,回调的时候发现订单失败了,不往下走了,就这个原因导致为什么我看到投标失败了但我的钱却冻结了!

   这时候不禁感觉一阵冷汗,要是以后搞什么秒杀活动,或者人气很高的时候,100个人都在定时任务扫描那个点投资出去那就悲剧了,可以想象一下100个人看到的结果都是失败,然后我们要么修改数据库,要么解冻用户钱,但带来的损失肯定没办法弥补了!

  于是进行思考和查阅代码后总结了如下2点:

  • 错开定时任务扫描时间,将订单ctime推迟5分钟,这样就不会把刚创建的订单扫描进去了。但存在问题是体验感下降了,比如用户在某银行操作失败,由于推迟了 ctime,用户需要多等5分钟才能操作。
  • 通过redis重复确认,因为确实会存在订单不存在的现象,但为了防止上面说那个情况(用户还没调到某银行定时任务提前发送这种情况),根据订单号唯一性,出现订单不存在则 存到redis,然后根据现在的时间和创建时间对比一次,发现是首次回查那么就把1设置成value,然后不让修改失败状态, 第二次回查的时候就保险很多了,中间起码有5分钟的响应时间,这时候value应该变成2,代表第二次回查。但第三次的时候就没必要设置value为3了,直接设置失败。

 之所以不存放数据库是因为考虑到后面如果有1万个订单要1万次入库,这样数据压力也会变大,而nosql是一个很好的选择。


 

以上是暂时想出来的2个办法,不过这肯定不是最好的办法,由于个人技术和能力有限,希望能在以后的路上通过不断实践和发现得到更多更好的办法,写下此记录用来回顾!

    

  

 

【原】关于定时回查出现的BUG有感