计数器算法
- 原理:在固定的时间窗口内,对请求进行计数,当请求数量达到设定的阈值时,就开始限流,拒绝多余的请求。例如,设定 1 分钟的时间窗口内允许最多 100 个请求,那么在这 1 分钟内每来一个请求,计数器就加 1,当计数器达到 100 后,后续的请求就会被拒绝,直到下一个 1 分钟开始,计数器重置为 0 重新计数。
- 优点:实现简单,易于理解和部署,在一些对精度要求不是特别高的场景下能很好地控制流量。
- 缺点:存在临界问题,比如在时间窗口切换的瞬间,可能会出现两倍于阈值的请求被允许,导致限流不够精确。
滑动窗口算法
- 原理:将时间窗口划分成更小的单元,比如将 1 分钟的时间窗口划分为 60 个 1 秒的小窗口,每个小窗口都有独立的计数器。随着时间的推移,窗口会像滑动一样移动,每过 1 秒,就会有一个新的小窗口进入时间窗口,同时最老的小窗口移出。通过对这些小窗口内的请求数量进行统计和累加,来判断是否超过限流阈值。
- 优点:相比计数器算法,能更精确地控制流量,解决了计数器算法在时间窗口切换时的临界问题。
- 缺点:实现相对复杂一些,需要维护多个小窗口的计数器,占用的内存空间相对较大。
漏桶算法
- 原理:可以想象有一个漏桶,请求就像水一样流入漏桶,而漏桶以固定的速率将水漏出。当水流入的速度超过漏桶的漏水速度时,漏桶就会被填满,此时再流入的水就会溢出,也就是请求被拒绝。漏桶算法能保证请求以固定的速率处理,起到平滑流量的作用。
- 优点:能够很好地平滑流量,保证系统以稳定的速度处理请求,适用于对流量稳定性要求较高的场景。
- 缺点:不能很好地利用系统的空闲资源,如果漏桶的漏水速度较慢,而系统还有处理能力时,也会拒绝请求,可能导致资源利用率不高。
令牌桶算法
- 原理:有一个令牌桶,系统会以固定的速率向令牌桶中放入令牌,每个请求在处理之前需要从令牌桶中获取一个令牌,如果令牌桶中没有令牌了,请求就会被拒绝。令牌桶有一定的容量限制,当令牌桶满了之后,新生成的令牌会被丢弃。
- 优点:既能限制流量的速率,又能在系统空闲时允许一定的突发流量,因为令牌桶可以预先积累一定数量的令牌。相比漏桶算法,能更合理地利用系统资源。
- 缺点:实现相对复杂一些,需要考虑令牌的生成、获取和存储等问题。
固定速率采样算法
- 原理:按照固定的时间间隔或者请求数量间隔对请求进行采样,只处理采样到的请求,其他请求则被丢弃或延迟处理。比如每 10 个请求中只处理第 5 个请求,或者每隔 1 秒处理一个请求,其余时间的请求都不处理。
- 优点:实现简单,能够在一定程度上控制请求的处理数量,降低系统负载。
- 缺点:可能会丢弃大量的请求,对业务的影响较大,而且不能很好地应对突发流量,因为它的采样策略是固定的,不考虑系统的实际负载情况。
自适应限流算法
- 原理:根据系统当前的负载情况、资源使用情况等动态地调整限流策略和阈值。例如,通过监控系统的 CPU 使用率、内存占用、响应时间等指标,当发现系统负载较高时,自动降低限流阈值,减少请求处理量;当系统负载较低时,适当提高限流阈值,充分利用系统资源。
- 优点:能够根据系统的实际情况自动调整限流策略,更好地适应不同的业务场景和流量变化,提高系统的稳定性和资源利用率。
- 缺点:实现难度较大,需要对系统的各项指标进行实时监控和分析,并且需要有合理的算法来根据这些指标调整限流策略,对技术要求较高。
分享
如何在分布式系统中实现限流算法?
怎样根据系统的实际情况选择合适的限流算法?