龙空技术网

一文读懂常用的四大限流算法?

从程序员到架构师 721

前言:

眼前大家对“阻塞窗口与慢启动算法”大致比较重视,咱们都想要剖析一些“阻塞窗口与慢启动算法”的相关知识。那么小编也在网络上网罗了一些对于“阻塞窗口与慢启动算法””的相关内容,希望小伙伴们能喜欢,姐妹们一起来了解一下吧!

限流,是指在高并发系统中,出现大面积的流量请求情况,来限制新的流量对系统访问的操作。主要是防止在大流量的情况下出现系统崩溃无法访问的问题。

在日常开发中常用的四种限流算法分别是计数器固定窗口算法、计数器滑动窗口算法、漏桶算法、令牌桶算法。下面就来分别介绍一下几种方法的使用。

计数器固定窗口算法

如图所示,可以将某一段时间作为一个窗口期,在这个窗口期中存在一个用来记录请求的计数器,来记录这个窗口期内接收到的请求的个数。每接收一个请求那么计数器就会进行加一操作。如果当计数器大于当前窗口期所设置的最大阈值之后,那么在当前窗口期运行时间内就要开启限流操作。当窗口期结束了之后,所有的计数器信息,窗口信息都进行重置,相当于重新建立了一个窗口期,如上图所示。

特点分析

通过上面的分析,可以知道,固定窗口大小可以对一段时间内的流量进行监控,但是存在一个问题就是对于流量的监控,是一段不确定的时间。

假设有一个窗口期为60秒,那么在60秒时间结束之后,窗口数据就会重置,这个时候就会出现这样一种情况,如果在第一个窗口期的最后一秒钟发送了1000个请求,在第二个窗口开启之后的第一秒又发送了1000个请求,这个时候在这两秒之内一共发送了2000个请求,但是,窗口阈值就是1000,但是实际上,在这2秒之内有2000个请求进入了系统,这个时候就会导致系统挂掉。

所以固定窗口的优势就在于实现起来比较简单,使用起来比较方便,但是缺点就如上面所说,容易形成突刺导致上面这种情况。基于这种情况,就提出了如下的这种解决方案。

计数器滑动窗口算法

如图所示,滑动窗口其实就是固定窗口的改良版本,其解决的问题就是在固定窗口中由于两个窗口的切换期会出现两倍流量进入系统的情况导致系统崩溃的问题。滑动窗口是在固定窗口的基础上,又将窗口大小进行了细分,然后每个小窗口对应一个时间段,并且与固定窗口一样,有属于自己独立的窗口计数器,当请求的时间点大于了当前节点之后,那么窗口就会移动到下一个小窗口上,并且将原来的窗口数据舍弃进行重新计数。

这里需要注意,所有小窗口请求的总数不能超过整个大窗口所设置的最大的阈值。这种操作的好处就是解决了由于窗口切换所带来的两倍请求的问题。

算法分析

从上面的分析可以知道,滑动窗口是在固定窗口的基础上对每个计时窗口进行了更小的拆分,然后小窗口去维护自己独立的计数器。当请求时间超过了当前窗口时间的时候,那么窗口就会往后移动到下一个窗口。在平移的时候会主动的丢弃原来窗口的数据,同时要保证的是所有小窗口的请求数不能超过大窗口设置的阈值。

从图中也可以看到,滑动窗口其实就是对固定窗口进行了时间上的升级。也就是说滑动窗口的时间粒度越细致,那么所限流的请求就越精准。

其实在TCP底层对于数据的读取上就是采用滑动窗口的方式来操作的,有兴趣的读者可以研究一下TCP底层滑动窗口读取数据的原理。

特点分析

滑动窗口算法的产生就是为了解决固定窗口窗口交换位置的流量并发问题,但是我们也知道它本身还是窗口算法所以还是不能完全避免两倍流量问题,所以就出现了漏桶算法。

漏桶算法

漏桶算法比较容易理解,相信很多人都见过装油、装醋的漏斗,因为瓶口的大小太小了,所以要通过漏斗往瓶子中加油加醋,这就类似于我们的系统设计。因为我们系统所能承受的流量就只有10,但是某一个时间内进入系统的请求是1000的话,显然无法直接进入。这个时候就需要漏斗来均衡这种流量上的差异,如图所示。

如图所示,请求进入之后首先会进入到漏桶中,然后漏桶以恒定的速率来将请求发送到后端的处理系统中,来保证系统的稳定性。但是需要注意,当漏桶达到自身的最大流量之后,就会溢出,这个时候所有进入到系统的请求都会被丢弃。

特点分析

由于漏桶的出流量速率是固定的,所以可以对系统本身流量做到很好的控制,这就解决了,由于外部流量的不稳定导致系统异常的问题。但是漏桶不能解决流量突发的问题,假设,我们的漏桶出速率是每秒5个请求,漏桶容量是30个,这个时候如果突然进入了100个请求,显然漏桶只能接收30个请求,其他的70个都将会被丢弃,但是接到的这30个请求也不是一次被处理的,后续所有的请求也都无法进入,所以对激增的流量控制并不是太友好。为了解决这个问题,就引入了令牌桶算法。

令牌桶算法

为了有效的解决漏桶所带来的请求阻塞问题,就引入了令牌桶算法。

令牌桶算法通过发放令牌,根据令牌的rate的频率来对请求频率做限制,对容量进行限制。是对漏桶的一种优化改进,解决了漏桶无法应对突发流量的问题。在令牌桶中,存在一个存放令牌的桶,然后存在一个令牌生成机制,以恒定的速度往桶里生成令牌,当然令牌桶也是有容量限制的,如果令牌慢了,没有被使用的话就会停止令牌的生成。

当一个请求进入之后,首先需要获取令牌,如果获取到了令牌,那么对应的请求就会被处理,并且销毁令牌,如果没有获取到令牌就说明进行流控了,该请求就会被丢弃拒绝。如上图所示。

那么为什么说令牌桶解决了漏桶对于并发流量处理不友好的问题呢?

特点分析

通过上面的分析我们知道,漏桶的大小是恒定的,也就是说强行的限制了请求的数量和请求处理速度,而令牌桶只是限制了令牌生成的速度,请求激增的时候,如果令牌桶中存在足够的令牌,那么所有的请求都会获取到令牌,都可以得到处理。这就避免了像是漏桶一样所带来的强行丢弃的那种情况发生。

总结

对于漏桶算法和令牌桶算法来讲,一个保证了恒定的速度的出流量,一个保证了恒定速度的入流量。也算是各有各的优势,所以在实际使用的时候要根据实际使用场景来选择合适的算法。而对于窗口算法来讲,使用起来相对于漏桶和令牌桶要简单方便,但是由于它与生俱来的窗口切换问题。所以在使用的时候要进行合理的评估。

标签: #阻塞窗口与慢启动算法