四种常见的限流算法

一、计数器算法

  • 计数器算法是限流算法里最简单也是最容易实现的一种算法,简单来说就是规定单位时间处理的请求数量。
  • 比如我们规定我们的一个接口一分钟只能访问100次的话。
  • 在一开始,我们设置一个计数器counter,每当一个请求过来,counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多,触发限流。
  • 如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter,具体算法的示意图如下(该图来自互联网):

四种常见的限流算法

  • 这个算法虽然简单,但是有一个十分致命的问题,那就是临界问题:假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。我们刚才规定的是1分钟最多100个请求, 瞬间超过我们我们阈值的两倍。用户有可能通过算法的这个漏洞,压垮我们的应用。

二、滑动窗口计数器算法

  • 计数器算法的升级版。

  • 滑动窗口计数器算法相比于固定窗口计数器算法的优化在于:它把时间以一定比例分片,例如我们可以把 1 分钟分为6个窗口。
    四种常见的限流算法

  • 如图,每格代表的是10秒钟。每过10秒钟,我们的时间窗口就会往右滑动一格。每一个格子都有自己独立的计数器counter,比如当一个请求 在0:35秒的时候到达,那么0:30~0:39对应的counter就会加1,红色虚线框住的六个格子的counter相加不能大于100。

  • 同样的临界问题,0:59到达的100个请求会落在蓝色的格子中,而1:00到达的请求会落在绿色的格 子中。当时间到达1:00时,我们的窗口会往右移动一格,那么此时时间窗口内的总请求数量一共是200个,超过了限定的100个,所以此时能够检测出来触发限流。

三、漏桶算法

  • 我们可以把发请求的动作比作成注水到桶中,我们处理请求的过程可以比喻为漏桶漏水。我们往桶中以任意速率流入水,以一定速率流出水。当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。
  • 实现这个算法的话也很简单,准备一个队列用来保存请求,然后我们定期从队列中拿请求来执行就好了。

四种常见的限流算法

四、令牌桶算法

  • 令牌桶算法和漏桶算法算法一样,我们的主角还是桶,不过现在桶里装的是令牌了。
  • 所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
  • 根据限流大小,设置按照一定的速率往桶里添加令牌;
  • 桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
  • 请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;

四种常见的限流算法