限流算法

在大型电商等系统中,我们回努力提升API的吞吐量和QPS(Query Per Second每秒查询量),但总归有上限。
为了应对巨大流量的瞬间提交,我们会做对应的限流处理。
那么何为限流呢?
顾名思义,限流就是限制流量,就像你手机包了1个月1个G的流量,用完了就没了,就必须等下一个月了。
通过限流,我们可以很好地控制系统的QPS,从而达到保护系统的目的。

算法确定参数空间复杂度时间复杂度限制突发流量平滑限流分布式环境下实现难度
固定窗口计数周期T、周期内最大访问数N低O(1)(记录周期内访问次数及周期开始时间)低 O(1)
滑动窗口计数周期T、周期内最大访问数N高O(N)(记录每个小周期中的访问数量)中O(N)滑动窗口的格子划分的越多,那么滑动窗口就越平滑
令牌桶令牌产生速度r、令牌桶容量N低O(1)(记录当前令牌桶中令牌数)高O(N)
漏桶漏桶流出速度r、漏桶容量N低O(1)(记录当前漏桶中容量)高O(N)

1、计数器(固定窗口)算法

计数器算法是使用计数器在周期内累加访问次数,当达到设定的限流值时,触发限流策略。下一个周期开始时,重新计数。
在这里插入图片描述
计数器法是限流算法里最简单也是最容易实现的一种算法。比如我们1分钟的访问次数不能超过100个。那么我们可以在一开始的时候设置一个计数器,每当一个请求过来的时候,计数器就加1;
如果计数器的值大于100并且当前请求与开始计数的时间间隔在1分钟之内,那么说明请求数过多,进行限流逻辑;
从计数开始到计数周期结束,需要重置计数器,具体算法的示意图如下:
在这里插入图片描述
计数器算法方式限流对于周期比较长的限流,存在很大的弊端(临界值合计超限),因为很有可能流量的分布式不均衡,例如流量全部集中在上一个周期的尾部以及现周期的头部。而这段期间的流量是非常大的,甚至不符合我们理解的1分钟内限流的要求。例如:
在这里插入图片描述
对于00:30至01:30这一区间1分钟的时间来说,流量达到了180,但是却并不违法。

2、计数器(滑动窗口)算法

针对固定时间窗口计数的问题,滑动窗口算法是将时间周期分为N个小周期,通过窗口向后滑动,统计窗口覆盖小周期的访问次数,以此进行是否满足限流判断,并且根据时间滑动删除过期的小周期。还是用上面的图演示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
按30秒作为一个小周期进行分别计数
00:00 - 01:00:滑动窗口框选1分钟的区间,此时合计调用次数为90次,不触发限流逻辑。
00:30 - 01:30:此时滑动窗口向后滑动,忽略或清除前面的小周期的计数,依然框选1分钟区间,此时合计调用次数为120次,触发限流逻辑。
01:00 - 02:00:此时滑动窗口向后滑动,忽略或清除前面的小周期的计数,依然框选1分钟区间,此时合计调用次数为95次,不触发限流逻辑。

以上例子由于滑动窗口也是按照一定周期30秒进行滑动的,依然会存在临界值合计超限的问题。
只有当滑动窗口的格子划分的越细,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。

3、令牌桶算法

令牌桶算法是程序以r(r=时间周期/限流值)的速度向令牌桶中增加令牌,直到令牌桶满,请求到达时向令牌桶请求令牌,如获取到令牌则通过请求,否则触发限流策略
在这里插入图片描述
从图中我们可以看到令牌桶算法,首先我们有一个固定容量的桶,桶里存放着令牌(token)。桶一开始是空的,token以一个固定的速率r往桶里填充,直到达到桶的容量,多余的令牌将会被丢弃。每当一个请求过来时,就会尝试从桶里移除一个令牌,如果没有令牌的话,请求无法通过。允许一定程度突发流量。

临界问题
我们再来考虑一下临界问题的场景,令牌桶内可以积累一定量的token,假如说是100个token,这100个请求可以瞬间被消费。但是由于token是以较低的速率填充的,积累到下一个100 token则必须等待那么长的时间。所以令牌桶算法可以很好地解决临界问题。

令牌桶算法实现上,可用乐观锁CAS实现,AtomicInteger。如使用Guava包中的RateLimiter。

4、漏桶算法

漏桶算法是访问请求到达时直接放入漏桶,如当前容量已达到上限(限流值)则进行丢弃(触发限流策略)。漏桶以固定的速率进行释放访问请求(即请求通过),直到漏桶为空。
在这里插入图片描述
从图中我们可以看到,漏桶算法其实十分简单。首先我们有一个固定容量的桶,有水流进来,也有水流出去。对于流进来的水来说,我们无法预计一共有多少水会流进来,也无法预计水流入的速度。但是对于流出去的水来说,这个桶可以固定水流出的速率,也一样可以很好地解决临界问题。

漏桶算法实现上,可以使用一个BlockingQueue表示漏桶,请求进来时放入这个BlockingQueue中。另起一个线程以固定的速率从BlockingQueue中取出请求,再提交给业务线程池处理。漏桶算法有个弊端:无法应对短时间的突发流量 。

令牌桶算法:允许流量一定程度的突发,因为默认的令牌桶算法,取走token是不需要耗费时间的,也就是说,假设桶内有100个token时,那么可以瞬间有100个请求通过。
漏桶算法:则严格控制水流出的速度,可以理解为对并发严格可控。
选择哪种限流算法,我们需要具体情况具体分析,只有最合适的算法,没有最优的算法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值