高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法

Posted 凌桓丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法相关的知识,希望对你有一定的参考价值。


限流

什么是限流?

限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的

一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。常见的限流操作如下:

  • 拒绝服务:当流量达到上限的时,直接把请求拒绝掉。
  • 延迟处理:将请求放入消息队列中,等到有能力处理时再从其中取出来处理,会存在延时。
  • 特权处理:对用户进行分级,对高优用户(如VIP)优先处理,其他用户延迟处理或拒绝服务。

为什么要限流?

在一些节假日、秒杀活动等用户高峰期时,用户的流量会急剧增加,而我们后端的服务器的处理能力是有限的,如果我们不能很好的处理这些流量,就会导致服务器崩溃宕机,从而影响服务的可用性。同时,对于一些不正常的流量,如爬虫、ddos等情况,我们也需要进行规避,因此限流是必不可少的。

通过限流,我们能够解决以下问题:

  • 热点业务带来的突发请求。
  • 调用方 bug 导致的突发请求。
  • 恶意攻击请求。


分布式限流

分布式限流就是在分布式系统下,控制每个服务器接收的请求数,以保证服务器来得及处理这些请求。

单机场景下

当我们的应用单机部署时,只要对单点应用进行了限流,那么应用所依赖的各种服务也都得到了保护。

分布式场景下

但是在企业实际的业务场景中,都会采取分布式系统。单个节点的限流只能保证当前节点的流量限制,而无法保护依赖的资源。即使对每一个节点都采取单点限流的方式,在集群扩缩容的时候也较为麻烦。

分布式限流

因此在分布式场景下,我们应当借助一些中间件如Redis、Sentinel、nginx来实现分布式限流,这样才能更加灵活的控制整个集群的请求限制。同时由于我们的限制是针对整个集群的,我们所依赖的资源也得到了保障。


限流算法

计数器算法

最简单的限流算法其实就是计数器,我们只需要针对不同的场景,对各种窗口进行计数。

固定窗口计数器

固定窗口计数器算法概念如下:

  • 将时间划分为多个窗口。
  • 在每个窗口内每有一次请求就将计数器加一。
  • 如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃当时间到达下一个窗口时,计数器重置。

固定窗口计数器

固定窗口计数器虽然实现简单,但是也面临着双倍突发的问题。

假设我们限制每秒钟只能处理10个请求,在上一个窗口的后半秒中通过了10个请求,在当前窗口的前半秒中又通过了10个请求,此时就在一秒钟内通过了20个请求,达到了窗口限制的两倍,这时就有可能超出了服务器的处理能力,从而导致宕机。

因此,又引入了滑动窗口计数器


滑动窗口计数器

滑动窗口计数器算法概念如下:

  • 将时间划分为多个区间。
  • 在每个区间内每有一次请求就将计数器加一维持一个时间窗口,占据多个区间。
  • 每经过一个区间的时间,则抛弃最老的一个区间,并纳入最新的一个区间。
  • 如果当前窗口内区间的请求计数总和超过了限制数量,则本窗口内所有的请求都被丢弃。

滑动窗口计数器

滑动窗口计数器是通过将窗口再细分,并且按照时间来滑动,这种算法避免了固定窗口计数器带来的双倍突发请求,但时间区间的精度越高,维护窗口的空间容量就越大。


上述计数器的实现方法,虽然实现起来非常简单,但是有一个致命的缺陷,就是无法解决突发的流量激增这一场景。

在实际场景中,流量并不会平滑到来,在某些特定的时间段如节日、使用热点等时间会存在突发的流量激增,在这种情况下很容易就会导致服务器性能打满,从而出现宕机等情况。因此,又引入了漏桶令牌桶算法。


漏桶算法

漏桶算法概念如下:

  • 将每个请求视作水滴放入漏桶进行存储。
  • 漏桶以固定速率向外漏出请求来执行,如果漏桶空了则停止漏水。
  • 如果漏桶满了则多余的水滴会因为溢出被直接丢弃。

如下图所示,水滴持续滴入漏桶中,底部定速流出。如果水滴滴入的速率大于流出的速率,当存水超过桶的大小的时候就会溢出。

漏桶算法

无论用户请求有多少,无论请求速率有多大,漏桶都会接收下来,同时漏桶里流出来的请求是固定速率的,即使是在流量激增的情况下,也保证了服务器能够平滑的处理。当漏桶因为容量限制放不下更多的请求时,就会选择丢弃部分请求。这种思路其实就是一种宽进严出的策略。

漏桶算法的缺陷也很明显,当短时间内有大量的突发请求时,即便此时服务器没有任何负载,每个请求也都得在队列中等待一段时间才能被响应。所以漏桶策略适用于间隔性突发流量且流量不用即时处理的场景


令牌桶算法

令牌桶策略,指的是桶里放着很多令牌,只有拿到令牌的请求才能被服务器处理

令牌桶算法概念如下:

  • 令牌以固定速率生成。
  • 生成的令牌放入令牌桶中存放,如果令牌桶满了则多余的令牌会直接丢弃。当请求到达时,会尝试从令牌桶中取令牌,取到了令牌的请求可以执行。
  • 如果桶空了,那么尝试取令牌的请求会被直接丢弃。

令牌桶算法

以上是关于高可用系统设计 | 分布式限流策略:计数器算法漏桶算法令牌桶算法的主要内容,如果未能解决你的问题,请参考以下文章

Java限流策略

Nginx限流和黑名单配置

读书笔记:限流详解

服务高可用利器——限流算法介绍与示例

服务高可用利器——限流算法介绍与示例

限流策略