限流算法

保护系统的第一道防线

🎯 面试重点

📖 限流算法

计数器算法

/**
 * 计数器算法
 * 
 * 原理:单位时间内允许 N 个请求
 * 
 * 问题:临界流量问题
 */
public class CounterRateLimiter {
    // 实现
    /*
     * // 简单实现
     * long now = System.currentTimeMillis();
     * if (count > limit) {
     *     return false;  // 限流
     * }
     * count++;
     * return true;
     * 
     * 问题:假设限流 100/秒
     * 0.9秒: 100个请求
     * 1.0秒: 清零
     * 1.1秒: 100个请求(0.9-1.1 秒有 200 个请求)
     */
}

滑动窗口算法

/**
 * 滑动窗口算法
 * 
 * 原理:将时间窗口分成多个小窗口
 *      统计各小窗口的请求数
 * 
 * 解决:计数器算法的临界问题
 */
public class SlidingWindow {
    // 示例
    /*
     * 窗口:60秒,分成 60 个 1 秒格子
     * 每次请求放对应格子
     * 统计窗口内总和
     */
}

漏桶算法

/**
 * 漏桶算法
 * 
 * 原理:以固定速率流出,桶满则丢弃
 * 
 * 特点:平滑处理,削峰填谷
 */
public class LeakyBucket {
    // 实现
    /*
     * 桶容量:bucketSize
     * 流出速率:rate
     * 
     * 请求来时:
     * 1. 桶是否已满? -> 丢弃
     * 2. 加入桶
     * 
     * 定时任务:
     * 以 rate 速率从桶中取出请求处理
     */
}

令牌桶算法

/**
 * 令牌桶算法
 * 
 * 原理:以固定速率放入令牌
 *      请求获取令牌后放行
 * 
 * 特点:允许突发流量
 */
public class TokenBucket {
    // 实现
    /*
     * 令牌桶容量:capacity
     * 令牌放入速率:rate
     * 
     * 请求来时:
     * 1. 桶中有令牌? -> 取令牌,放行
     * 2. 无令牌 -> 限流
     */
}

📖 限流实现

本地限流

/**
 * 本地限流实现
 */
public class LocalRateLimit {
    // Guava RateLimiter
    /*
     * RateLimiter limiter = RateLimiter.create(100);  // 每秒 100 个
     * if (limiter.tryAcquire()) {
     *     // 处理请求
     * } else {
     *     // 限流
     * }
     */
    
    // 滑动窗口限流
    /*
     * 使用 Redis 的滑动窗口
     * ZADD, ZRANGEBYSCORE, ZREM
     */
}

分布式限流

/**
 * 分布式限流实现
 */
public class DistributedRateLimit {
    // 1. Redis 计数器
    /*
     * INCR key
     * EXPIRE key 1
     */
    
    // 2. Redis + Lua
    /*
     * 原子操作保证准确性
     */
    
    // 3. Sentinel
    /*
     * 阿里巴巴的限流组件
     * 支持多种限流策略
     */
    
    // 4. OpenResty
    /*
     * 基于 Nginx 的限流
     */
}

📖 面试真题

Q0: 限流的常见算法?

答: 常见的限流算法主要有以下几种:

1. 计数器算法(固定窗口)

2. 滑动窗口算法

3. 漏桶算法

4. 令牌桶算法

对比总结

Q1: 限流算法对比?

答:

Q2: 令牌桶和漏桶的区别?

答: 令牌桶允许一定程度的突发流量,漏桶严格以固定速率处理。


⭐ 重点:限流是保护系统的核心手段,必须掌握各算法原理