常见的限流算法主要有以下几种:
计数器算法
- 原理:在固定时间窗口内,对请求进行计数,当请求数达到设定的阈值时,就开始限流,拒绝后续请求。例如,在 1 分钟的时间窗口内,设定阈值为 100 次请求,每来一次请求,计数器就加 1,若 1 分钟内请求次数超过 100 次,后续请求就会被限制。
- 优点:实现简单,易于理解和部署。
- 缺点:存在临界问题,比如在时间窗口切换时,可能会出现双倍阈值的请求量,导致限流不够精确。
漏桶算法
- 原理:把请求看作是水,将水倒入漏桶中,漏桶以固定的速率出水(处理请求),如果水的流入速度超过了漏桶的出水速度,那么多余的水就会溢出(请求被拒绝)。
- 优点:可以平滑请求,能有效应对突发流量,保证系统以稳定的速率处理请求。
- 缺点:不能充分利用系统资源,因为即使系统在某个时刻有空闲资源,也只能按照固定速率处理请求。
令牌桶算法
- 原理:系统会以固定的速率向令牌桶中放入令牌,每个请求在处理之前需要从令牌桶中获取一个令牌,如果令牌桶中没有令牌了,那么请求就会被拒绝。
- 优点:能在限制流量的同时,允许一定程度的突发流量,只要令牌桶中有足够的令牌,就可以处理突发的大量请求,相对漏桶算法能更充分地利用系统资源。
- 缺点:实现相对复杂一些,需要维护令牌桶的状态,包括令牌的生成和获取等操作。
滑动窗口算法
- 原理:将时间窗口进行细分,例如把 1 分钟的时间窗口划分为 60 个 1 秒的小窗口,每个小窗口都有独立的计数器。随着时间的推移,时间窗口像滑动窗口一样不断移动,通过统计滑动窗口内的请求数量来判断是否需要限流。
- 优点:相比简单的计数器算法,能更精确地控制流量,解决了计数器算法在时间窗口切换时的临界问题。
- 缺点:实现相对复杂,需要更多的存储空间来记录每个小窗口的请求计数,性能开销相对较大。
分布式限流算法(基于 Redis 的令牌桶或计数器)
- 原理:在分布式系统中,利用 Redis 的原子指令和数据结构来实现限流。比如使用 Redis 的原子计数指令来实现计数器算法,或者利用 Redis 的有序集合等数据结构来实现令牌桶算法,通过在多个节点之间共享和同步限流状态,实现分布式环境下的统一限流。
- 优点:能很好地适应分布式系统的场景,保证整个分布式系统的限流效果。
- 缺点:依赖于 Redis 等外部组件,增加了系统的复杂性和维护成本,同时需要考虑网络延迟等因素对限流效果的影响。