前几天遇到一个有关于“月末清零”的业务场景下的异常问题,在这里跟大家分享一下。
一、场景
这是一个高并发下的流控场景,每个用户每月使用API都设定一个阀值,超出阀值的调用受限。
二、原程序设计
程序设计需要记录用户对API的使用量,这里使用redis存储计数。当月底时对使用量进行清零。清零的定时任务设定在月末最后一天的23:59:00,之所以未设定零点,是因为零点的定时任务太多了,0点执行后到完成有一定的延时,这段时间的调用不会被记入本月,所以,虽然23:59:00一样使数据切割的不准确,但是也可以接受。
然后,问题来了。
三、问题
主要是下面几个问题:
1程序在月末零点前后宕机或关闭,导致定时任务未执行。
2.因系统压力等因素,本应23:59:00执行的定时任务直到零点后才执行。然而这时判断已不是月末最后一天,任务内容未正常执行。
类似上面问题导致的后果就是,上月的调用量计数累计到了下个月,数据异常了。
四、优化
如何避免这个问题呢,能否是数据切割变得自然而准确呢?
来看看这个方案:
redis中计数的key按月区分,如:key202105,key202106.
在调用计数时,获取当前月份拼接key来计数,月份交界点完美切换,而且无需额外定时任务操作数据。控制台等需要处理数据是也以月份维度来处理。
对比两个方案就发现,第二种方案跟合理准确。逻辑跟简单。
好的设计可以大大提高系统的性能、稳定性,降低复杂度等等优点,所以,在设计上多下功夫是绝对值得的。
作者:Alanwalker
来源:移动云开发者社区