限流算法【面试】

针对软件系统来说,限流就是对请求的速率进行限制,避免瞬时的大量请求击垮软件系统。毕竟,软件系统的处理能力是有限的。如果说超过了其处理能力的范围,软件系统可能直接就挂掉了。

限流可能会导致用户的请求无法被正确处理或者无法立即被处理,不过,这往往也是权衡了软件系统的稳定性之后得到的最优解。

现实生活中,处处都有限流的实际应用,就比如排队买票是为了避免大量用户涌入购票而导致售票员无法处理。

常见限流算法有哪些?

固定窗口计数器算法

系统单位时间内处理请求

缺点:请求在单位时间内分布不均衡

固定窗口其实就是时间窗口,其原理是将时间划分为固定大小的窗口,在每个窗口内限制请求的数量或速率,即固定窗口计数器算法规定了系统单位时间处理的请求数量。

假如我们规定系统中某个接口 1 分钟只能被访问 33 次的话,使用固定窗口计数器算法的实现思路如下:

  • 将时间划分固定大小窗口,这里是 1 分钟一个窗口。

  • 给定一个变量 counter 来记录当前接口处理的请求数量,初始值为 0(代表接口当前 1 分钟内还未处理请求)。

  • 1 分钟之内每处理一个请求之后就将 counter+1 ,当 counter=33 之后(也就是说在这 1 分钟内接口已经被访问 33 次的话),后续的请求就会被全部拒绝。

  • 等到 1 分钟结束后,将 counter 重置 0,重新开始计数。

固定窗口计数器算法

优点:实现简单,易于理解。

缺点:

  • 限流不够平滑。例如,我们限制某个接口每分钟只能访问 30 次,假设前 30 秒就有 30 个请求到达的话,那后续 30 秒将无法处理请求,这是不可取的,用户体验极差!

  • 无法保证限流速率,因而无法应对突然激增的流量。例如,我们限制某个接口 1 分钟只能访问 1000 次,该接口的 QPS 为 500,前 55s 这个接口 1 个请求没有接收,后 1s 突然接收了 1000 个请求。然后,在当前场景下,这 1000 个请求在 1s 内是没办法被处理的,系统直接就被瞬时的大量请求给击垮了。

qps(每秒钟查询的次数)

滑动窗口计数器算法

时间以一定比例分片(每单位时间(一秒)都记录一次固定时间(一分钟)接收的请求)

缺点:需要存储的数据多

滑动窗口计数器算法 算的上是固定窗口计数器算法的升级版,限流的颗粒度更小。

滑动窗口计数器算法相比于固定窗口计数器算法的优化在于:它把时间以一定比例分片

例如我们的接口限流每分钟处理 60 个请求,我们可以把 1 分钟分为 60 个窗口。每隔 1 秒移动一次,每个窗口一秒只能处理不大于 60(请求数)/60(窗口数) 的请求, 如果当前窗口的请求计数总和超过了限制的数量的话就不再处理其他请求。

很显然, **当滑动窗口的格子划分的越多,滑动窗口的滚动就越平滑,限流的统计就会越精确。

滑动窗口计数器算法

优点:

  • 相比于固定窗口算法,滑动窗口计数器算法可以应对突然激增的流量。

  • 相比于固定窗口算法,滑动窗口计数器算法的颗粒度更小,可以提供更精确的限流控制。

缺点:

  • 与固定窗口计数器算法类似,滑动窗口计数器算法依然存在限流不够平滑的问题。

  • 相比较于固定窗口计数器算法,滑动窗口计数器算法实现和理解起来更复杂一些。

漏桶算法

我们可以把发请求的动作比作成注水到桶中,我们处理请求的过程可以比喻为漏桶漏水。我们往桶中以任意速率流入水,以一定速率流出水。当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。

如果想要实现这个算法的话也很简单,准备一个队列用来保存请求,然后我们定期从队列中拿请求来执行(和消息队列削峰/限流的思想是一样的)

漏桶算法

优点:

  • 实现简单,易于理解。

  • 可以控制限流速率,避免网络拥塞和系统过载。

缺点:

  • 无法应对突然激增的流量,因为只能以固定的速率处理请求,对系统资源利用不够友好。

  • 桶流入水(发请求)的速率如果一直大于桶流出水(处理请求)的速率的话,那么桶会一直是满的,一部分新的请求会被丢弃,导致服务质量下降。

实际业务场景中,基本不会使用漏桶算法。

令牌桶算法

令牌桶算法也比较简单。和漏桶算法算法一样,我们的主角还是桶(限流算法和桶过不去)。不过现在桶里装的是令牌了,请求在被处理之前需要拿到一个令牌,请求处理完毕之后将这个令牌丢弃(删除)。我们根据限流大小,按照一定的速率往桶里添加令牌。如果桶装满了,就不能继续往里面继续添加令牌了。

令牌桶算法

优点:

  • 可以限制平均速率和应对突然激增的流量。

  • 可以动态调整生成令牌的速率。

缺点:

  • 如果令牌产生速率和桶的容量设置不合理,可能会出现问题比如大量的请求被丢弃、系统过载。

  • 相比于其他限流算法,实现和理解起来更复杂一些。

著作权归JavaGuide(javaguide.cn)所有
基于MIT协议
原文链接:服务限流详解 | JavaGuide

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值