当前位置: 面试刷题>> 什么是限流?有哪些常见的限流算法?(经典算法150题)


在软件开发与系统架构设计中,限流(Rate Limiting)是一种重要的技术手段,用于控制接口或服务的访问频率,以保护系统免受过量请求的冲击,确保服务的稳定性和可靠性。限流机制能够有效避免服务因过载而崩溃,同时也能公平地分配系统资源给各个请求者。下面,我将从高级程序员的视角,详细解析限流的概念、常见算法,并附上示例代码。 ### 什么是限流? 限流,简而言之,就是对某个接口或服务的请求速率进行限制,以防止其被过度使用。通过设定合理的请求阈值(如每秒请求数、每分钟请求数等),系统能够自动拒绝超过限制的请求,或是对这些请求进行排队等待处理,从而保护系统资源不被耗尽。 ### 常见的限流算法 1. **固定窗口算法(Fixed Window)** 固定窗口算法是最简单的限流算法之一,它将时间划分为若干个固定长度的窗口,每个窗口内独立计数。超过窗口内设定阈值的请求将被拒绝。这种方法实现简单,但存在边界问题,即窗口切换瞬间可能突然放行大量请求,造成“突刺”现象。 ```python import time class FixedWindowRateLimiter: def __init__(self, limit, window_size): self.limit = limit self.window_size = window_size self.current_window = time.time() // self.window_size self.count = 0 def allow_request(self): now = time.time() if now // self.window_size > self.current_window: self.current_window = now // self.window_size self.count = 0 if self.count < self.limit: self.count += 1 return True return False ``` 2. **滑动窗口算法(Sliding Window)** 滑动窗口算法是对固定窗口算法的改进,它通过维护一个连续的、可滑动的窗口来记录请求次数,有效解决了固定窗口算法的边界问题。滑动窗口算法可以更加平滑地控制请求速率。 由于滑动窗口算法的实现相对复杂,通常不会直接手动编写代码实现,而是会利用现有的库或框架支持,如Redis的令牌桶(Token Bucket)或漏桶(Leaky Bucket)算法实现。 3. **令牌桶算法(Token Bucket)** 令牌桶算法是另一种常见的限流算法,它通过一个固定容量的桶来存储令牌(代表请求权限),系统以恒定速率向桶中添加令牌。请求到达时,会从桶中移除一个令牌,如果桶中没有令牌,则请求被拒绝。令牌桶算法能够允许一定程度的突发流量,且实现较为简单。 ```python import threading import time class TokenBucketRateLimiter: def __init__(self, rate, capacity): self.rate = rate # 每秒添加令牌的数量 self.capacity = capacity # 桶的容量 self.tokens = capacity self.last_time = time.time() self.lock = threading.Lock() def allow_request(self): with self.lock: now = time.time() # 添加令牌 while now > self.last_time: self.tokens = min(self.capacity, self.tokens + (now - self.last_time) * self.rate) self.last_time = now if self.tokens > 0: self.tokens -= 1 return True return False ``` 4. **漏桶算法(Leaky Bucket)** 漏桶算法与令牌桶算法类似,但它以恒定的速率处理请求,无论请求到达的速率如何。漏桶有一个固定的容量,且以恒定的速率向外“漏水”(处理请求)。如果桶满,则新到达的请求将被丢弃或等待。漏桶算法适用于需要严格控制请求处理速率的场景。 漏桶算法的实现与令牌桶类似,但核心逻辑在于控制请求的处理速率而非添加令牌的速率。 ### 结论 限流是保障系统稳定、防止服务过载的重要手段。在实际应用中,选择合适的限流算法需根据具体场景和需求来决定。固定窗口算法简单直观,但可能引发突刺问题;滑动窗口算法解决了固定窗口的问题,但实现较为复杂;令牌桶和漏桶算法则提供了更为灵活和强大的限流能力,能够应对不同类型的请求模式。作为高级程序员,理解并掌握这些限流算法,对于设计高可用、可扩展的系统至关重要。在实践中,还可以结合具体的技术栈(如Redis、Guava等)来简化限流逻辑的实现。
推荐面试题