常见限流算法分析

背景介绍

限流的目的是通过对并发访问请求进行限速或者一个时间窗口内的的请求数量进行限速来保护系统,一旦达到阈值则可以拒绝服务、排队或等待
限流,从分布式角度,可以分为分布式限流和单机限流。从算法维度,可以分为计数器算法、滑动时间窗口算法、漏桶算法、令牌桶算法等。
关于限流的文章非常多,但是很多文章都只是侧重在原理介绍和代码实现,很多时候大家在要做系统限流功的时候想着实现了限流就可以了,却没有深究,我选择的这个算法到底有没有问题,在特定场景下到底是不是最优方案。因此,本文在进行算法分析的基础上,着重对比各个算法的优劣进行分析,在实际的场景进行限流方案的选取的时候,可以做为参考。

算法分析

计数器算法

常见限流算法分析_第1张图片
计数器算法(网图)
在计数器算法中,对一定时间区间内,进行计数,与限流值上限进行比较,到了时间临界点,将计数器清0。
举个例子:对于某个接口,1分钟的访问次数不能超过100次。在开始的时候,设置一个限流计数器counter,每当一个请求进入系统,counter值加1,如果counter值大于100且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多;如果该请求与第一个请求间隔时间大于1分钟,且counter值还在限流上限范围内,则重置 counter。

  • 优点

原理简单,实现方便;

  • 缺点

临界问题
当遇到恶意请求,在0:59时,瞬间请求100次,并且在1:00请求100次,那么这个用户在1秒内请求了200次,用户可能会在重置节点(即0:59和1:00)发起大量请求,而瞬间超过我们设置的速率限制,攻击者也可能通过重置节点发起大量请求来击垮应用。
突刺问题
意请如果1s的前1ms,已经有100个请求,那么后面的999ms,会拒绝所有的请求,业务处理全部暂停,这种现象称为“突刺问题”。

滑动时间窗口算法

常见限流算法分析_第2张图片
滑动时间窗口算法示意图(网图)
在滑动时间窗口算法中,以当前时间为截止时间,往前特定的时间作为一个时间区间。先清除上一个时间区间内的请求记录,再计算当前时间区间内请求数量是否大于设定的最大请求数,如果超过则执行限流策略,否则插入本次请求记录并受理请求。

  • 优点

无“临界问题”
0:59到达的100个请求会落在灰色的格子中,而1:00到达的请求会落在橘黄色的格 子中。当时间到达1:00时,我们的窗口会往右移动一格,此时新的一格又可以受理新的请求,不会因为“临界问题”导致整个2分钟内只有0:59和1:00处理200个请求,其他时刻系统由于触发限流阈值,所有请求全部被丢弃。

分析完滑动时间窗口算法,再对刚才的计数器算法进行回顾,计数器算法本质上是也是滑动窗口算法,只是没有对时间窗口做进一步地划分,划分的区间只有1格。而对滑动时间窗口算法进行分析可以发现:当滑动窗口的格子划分的越多,那么滑动窗口的滑动所覆盖的时间区间就会越小,限流的统计就会越精确。

漏桶算法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9Qi4X9r-1679992109410)(https://cdn.nlark.com/yuque/0/2022/png/2757062/1657088969045-44437107-633b-4ca4-be80-5750bf59bbd8.png#averageHue=%23f5f5f5&clientId=ua1ad672d-f5de-4&from=paste&id=udc69a2ec&name=image.png&originHeight=299&originWidth=443&originalType=url&ratio=1&rotation=0&showTitle=false&size=30770&status=done&style=none&taskId=ue2badafc-9b05-4741-996e-7f4c3e04d6a&title=)]
漏桶算法示意图(网图)
在漏桶算法中,将流量放入桶中,漏桶同时也按照一定的速率流出,当水流入速度过大会直接溢出,可以看出漏桶算法能限制数据的传输速率
如果流量过快的话就会溢出,溢出的流量则直接丢弃。

  • 优点

原理简单,实现方便;
无“临界问题”,漏桶“按照一定的速率流出”,所以系统会以一个常速速率来处理请求,不会出现临界问题;

  • 缺点

由于是**“按照一定的速率”**进行处理,当流量短时间内暴增的时候,无法应对,对于整点大促、秒杀等场景,短板明显;

令牌桶算法

常见限流算法分析_第3张图片
令牌桶算法示意图(网图)
在令牌桶算法中,令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌。如果桶满了,新放入的令牌会被丢弃。令牌生成的速率可以控制,令牌桶算法通过令牌生成速率根据可以做请求频率限制,容量限制。当有流量来时则取走一个或多个令牌。当桶中没有令牌则将当前请求丢弃或阻塞。

  • 优点

无“临界问题”
在0:59秒的时候,由于桶内积满了100个token,所以突发的100个请求可以瞬间被处理,由于token是以较低的速率填充的,在1:00时,桶内的token数量不会达到100个,那么此时不可能再有100个请求通过。令牌桶算法通过这种方式解决临界问题。

可以应对突发流量

生成令牌的速率恒定,请求获取令牌不会进行速度限制(漏桶算法限制了请求获取令牌的速度),所以在面对瞬间大流量的时候,也可以在短时间内拿到大量令牌。

  1. 计数器算法 - 当机器处理效率低于一个时间段间隔内的请求数量时,请求队列整体会增加直到请求超时。( 请求每一个时间段内都是打满 )
  2. 滑动窗口 - 其实就是计数器, 在每一个时间间隔都允许部分请求请入,不过整体请求数量有限制( 滑块限制 ),单个时间间隔可请求数量会被滑块内请求影响。
  3. 漏桶算法: 把桶看作滑块的窗口,恒定速率处理多少,往前滑多少,可再接多少请求,
  4. 令牌桶: 这个桶只是某一刻最大请求数量,突刺阶段会尽可能的接受请求, 超过桶限制直接丢弃,后续阶段低速率接受请求 ( 速率小于处理效率 ),这样可以把之前接受的请求慢慢消耗掉。

这些算法一些在说明请求策略,反过来可以当作请求拒绝策略,防止过多请求把服务器打卦,更多的算法是限制某一刻或者某一段时间内的请求,下一段时间接受请求多少数量可以被现有数量影响 ( 滑块 )、可以被机器影响 ( 漏桶、令牌桶 )

你可能感兴趣的:(java,开发语言)