未加星标

集群限流的一次坑坑坑

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二04 | 时间 2018 | 作者 红领巾 ] 0人收藏点击收藏

之前在一篇文章中提到过,因为业务的集群限流需求,在每次请求都需要拿到当前的日期,不过精确到天即可。上次给出的解决方案是,因为Calendar的性能问题,选择更加直接粗暴的方式,就是下面这个。

private static final int DAY_MILLIS = 24 * 60 * 60 * 1000; long day = System.currentTimeMillis() / DAY_MILLIS;

通过当前的时间戳(毫秒级别),除以一天的毫秒数,得到的结果就是从1970 到今天经历过的天数。

最近业务在使用限流功能时,需要实现限制接口每天调用1w次。

只是,第一个版本的实现逻辑是这样的,如果第一个请求是早上8点过来的,那么会在redis创建一个对应的key,并设置24小时过期。所以从今天早上8点到明天早上8点,只能调用1w次,多余的就拒绝,所以每天限制的时间段可能是不一样的。

业务提出了新需求:必须按照0点到第二天0的时间段进行限制。

对于这个需求,我表示会心一笑,上述的粗暴方案不是正好满足么,三下五除二,就给加上了这个功能。

if (timeUnit == TimeUnit.DAYS) { key = ruleId + TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis()); }

如果业务配置的限流周期是天,那么就在原始id上再加上当前的天数当前redis的key,那么每天的key都是不一样的,新的一天,都会有一个新的key,如此的美好。

业务使用改进后的版本上线了2天,甩过来一个监控页面,开始diss我们了,为什么昨天触发了限流,今天凌晨2点多还在限流。看着埋点数据,发现这个锅是甩不掉了,只能开始翻代码,无果。

后来通过redis的埋点数据,发现2点多操作的redis key上还是昨天的天数。很奇怪,有木有?明明已经2点了,怎么还是昨天的天数,我已经开始怀疑服务器的时间是不是有问题,居然鬼使神差的让业务去验证服务器的时间,结果是我被打脸了。

到最后,我才把关注点放在了 System.currentTimeMillis() 这个返回值上,这个返回的时间戳是从1970开始到现在格林威治时间的时间戳,而北京时间比格林威治整整快了8个小时。

所以真相是,通过暴力方案返回的天数,在北京时间早上8点之前都算是之前一天,过了8点,才算是新的一天,才会使用新的redis key进行计数。

继续修复,继续发版,下次在使用这种暴力方案时,考虑一下时区问题。

本文数据库(综合)相关术语:系统安全软件

tags: key,限流,redis,天数,currentTimeMillis,时间,业务,早上,DAY,MILLIS,1w
分页:12
转载请注明
本文标题:集群限流的一次坑坑坑
本站链接:https://www.codesec.net/view/597066.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(10)