限流算法能够帮助更好地管理和控制请求流量,下面给介绍6种常用的限流算法@mikechen
计数限流算法
计数限流算法是一种常见的限流策略,它基于请求次数来控制对系统的访问。
如下图所示:
计数限流算法的思想:
该算法在一定时间窗口内统计请求次数,一旦请求次数超过设定的阈值,就会触发限流机制。
例如:如果你设置每秒允许 100 个请求,那么在每个一秒的时间窗口内,只有前 100 个请求可以通过,超过这个数量的请求将被限流。
计数限流算法的优点是简单直观,易于实现。
但它也存在一些问题,例如:
- 时延问题: 由于计数限流只考虑请求次数,而不关心请求的处理时间,因此可能会导致某些请求的响应时间变得很长,从而影响用户体验。
- 突发请求: 在窗口期开始时,可能会有大量的请求进入系统,导致超过阈值,而在其余时间窗口内则没有请求。
计数限流算法可能会导致一些请求在整个窗口期内被限流,所以后续改进了,就有了滑动窗口限流算法。
滑动窗口限流算法
类似于固定窗口计数,但是会以滑动的方式来计算请求次数。
滑动窗口计数的思路,如下图所示:
- 定义时间窗口和计数器:将固定的限流窗口分成更小的计数窗口,每个小的窗口都一个单独的计数器;
- 请求计数: 当请求落到这个小的窗口内时,对应的计数器+1;
- 限流判断: 对于每个时间窗口,检查其中的请求计数器是否超过设定的阈值,如果超过了阈值,则触发限流机制,拒绝当前请求。
- 计数器更新: 随着时间的推移,请求计数器会在滑动过程中不断更新,当一个时间窗口结束时,计数器会被清零,新的时间窗口开始。
- 平滑限流: 由于滑动窗口的特性,算法可以更平滑地控制请求速率,避免了固定窗口限流可能出现的突发流量问题。
滑动窗口限流算法的优点:
滑动窗口限流算法可以平滑地控制请求的流入,避免了突发流量对系统造成的冲击,从而保持系统的稳定性。
滑动窗口限流算法的缺点:
- 复杂性: 相对于简单的计数限流算法,滑动窗口限流算法的实现可能会更复杂一些,涉及到时间窗口的管理和计数器的维护。
- 内存占用: 如果时间窗口较小,可能需要维护多个时间窗口和计数器,增加了内存占用。
- 对实时性要求: 尽管滑动窗口限流平滑了流量,但在某些实时性要求很高的场景下,仍可能出现请求延迟的情况。
漏桶算法
漏桶算法是一种常用于流量控制和限流的算法,它的原理类似于一个漏斗,用来平滑处理流入的请求,并以恒定的速率将请求排出系统。
如下图所示:
漏桶算法的思想和原理:
- 固定容量的漏桶: 系统维护一个固定容量的漏桶,用来存放请求。
- 请求入桶: 当一个请求到达系统时,相当于将水倒入漏桶。如果漏桶已满,多余的请求会被丢弃或拒绝。
- 恒定速率的出桶: 漏桶以恒定的速率处理请求,就像漏斗中的水稳定地漏出一样。
- 平滑流量: 通过漏桶的出水速率,可以平滑流入系统的请求,避免突发流量。
- 限流判断: 当一个请求到达时,会检查漏桶是否已满,如果漏桶已满,则触发限流机制,拒绝请求。
漏桶算法的优点:
是可以有效地控制流量,避免系统遭受突发请求的冲击,从而保持系统的稳定性。
漏桶算法的缺点:
然而,漏桶算法可能会导致某些请求的响应时间变长,因为请求需要等待漏桶处理完成才能被处理。
此外,漏桶算法不适用于实时性要求很高的场景,因为请求会被固定速率地处理。
令牌桶算法
令牌桶可以看作是一个存放令牌的容器,预先设定一定的容量,系统按设定的速度向桶中放置令牌,当桶中令牌满时,多余的令牌溢出。
如下图所示:
令牌桶算法流程,大致分为如下三步:
第一步:放入令牌到桶
按照固定的速率被放入令牌桶中,比如每秒放10个、100个、1000个令牌到桶中。
第二步:获取令牌
所有的请求在处理之前都需要拿到一个可用的令牌才会被处理。
第三步 :令牌桶满了拒绝
比如:桶中最多能放10000个令牌,当桶满时,就不能继续放入了,新添加的令牌要么被丢弃,要么就直接拒绝。
令牌桶算法的优点包括:
- 平滑流量: 令牌桶算法可以平滑地控制请求速率,避免了突发流量对系统的冲击。
- 适应性: 令牌桶算法适用于不同的时间尺度,可以用于毫秒级、秒级、分钟级等不同粒度的流量控制。
- 灵活性: 可以根据需求调整令牌生成速率和令牌桶的容量,以适应不同的流量控制需求。
然而,令牌桶算法也存在一些缺点,例如:
- 不适合瞬时突发流量: 令牌桶算法可能无法处理突然涌入的大量请求,因为令牌桶的令牌生成速率是固定的。
- 延迟问题: 如果请求需要等待令牌桶中的令牌,可能会导致一些请求的响应时间增加。
5.基于负载的限流
基于负载的限流算法是一种根据系统当前的负载情况动态调整请求的速率的限流策略。
以下是基于负载的限流算法的一般思路:
- 资源监控: 监控系统的资源使用情况,如 CPU 使用率、内存占用、网络带宽等。这可以通过系统监控工具或指标收集系统性能数据来实现。
- 阈值设定: 根据资源使用情况设置不同的负载阈值。例如,当 CPU 使用率超过 80% 时,认为系统负载较高。
- 动态调整: 根据实时监控数据,动态地调整请求速率。当负载高于阈值时,降低请求速率;当负载低于阈值时,逐步提高请求速率。
- 平滑调整: 为了避免频繁调整,可以使用平滑的方式进行速率调整,例如使用滑动窗口平均值来平滑负载变化。
6.基于权重的限流
基于权重的限流算法是一种根据请求的类型或优先级分配不同的权重,从而控制不同类型请求的流量。
基于权重的限流算法的核心思想是为每个请求类型分配一个权重值,然后根据这些权重值来调整每个类型请求的处理速率。通常,权重值可以是一个相对比例,也可以是一个具体的数值。
以下是基于权重的限流算法的一般思路:
- 请求分类: 首先,将不同类型的请求进行分类,可以根据业务功能、优先级等标准进行分类。
- 权重分配: 为每个请求类型分配一个权重值,表示其相对重要性或处理优先级。
- 限流控制: 根据权重值来调整每个请求类型的处理速率。高权重类型的请求可以被允许更多的通过,低权重类型的请求则被限制。
- 动态调整: 在运行时,可以根据实际需求动态地调整权重值,以适应业务变化。
不同的限流算法适用于不同的场景和需求,合理的限流可以保护系统免受过多请求的影响,从而确保系统的可用性和稳定性。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》