一次毫秒级的时间差导致的业务异常

1. 业务问题描述

线上有一个应用的某个接口调用量限制是1,000,000次,但是在早上9时左右,统计结果中显示本月的已调用量是1,043,222次,剩余调用量为0次,进而导致该应用无法正常调用该接口。如下图所示

2. 问题跟踪

据平日里的观察发现,该应用对该接口的一天调用量都是在10万以下,不太可能一下子就超过100万。首先,将整个代码流程看了一遍,似乎没有什么逻辑问题。然后线上日志查询,该接口当天第一次接口请求是调用成功的,但是在后续的调用结果中就是调用失败的。而且,统计出来本月的已调用量=该接口总调用量+本月前几日调用量之和+1,也就是说,统计出来的调用量比实际的调用量多了一百万。但是代码中又看不出来任何问题。

在日志查询的时候注意到,日志输出的时间距离零点非常近,然后,由查询了前一天和当天的日志,发现整个流程从前一日的23时59分59秒就开始了,到当日的0时0分0秒左右结束,整个过程执行完也就100毫秒左右。这里有必要简单介绍一下程序流程:

接口请求时,先进入鉴权模块,再进入接口调用模块,在鉴权模块时,会将数据库里的调用量写入缓存,缓存的key是apiFlow_appkey_apiId_curDate,再调用模块会采用redis的递减算法将该key的值减一。【鉴权写入,调用减一】

而造成上述异常的原因是:在整个流程中,都没有将日期参数传递,而是直接获取系统当前日期。在鉴权的时候,服务还是在前一日的23时59分59秒,而调用的时候是在当日的0时0分0秒,因此,在进行减一操作时,系统中并没有当日的缓存,因此直接从0开始减一。举例说明一下:

正常情况:假设接口最大调用限制是100次,调用1次后,缓存里的剩余调用是99次。因此,已调用量是1,剩余调用量是99;

异常情况:假设接口最大调用限制是100次,由于上述描述的毫秒级时间误差,调用一次后,缓存里的剩余调用量是-1,因此,已调用量是101次【调用量最大调用次数-剩余调用量=100 - (-1)= 101】,剩余调用量 =-1 < 0,返回给前端的是0。

而我们业务问题就属于上述的异常情况。

3. 解决办法

既然日期是一个比较关键的信息,因此从程序进入时,就应该将系统当前日期保存到请求头中,在后续的请求中从请求头中获取该日期。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值