日期:2026-07-11
标签:#面试 #八股 #后端 #系统设计 #场景题
一句话答案
限流是在资源容量边界前拒绝或延迟部分请求,常见算法有固定窗口、滑动窗口、漏桶和令牌桶,其中令牌桶最适合允许一定突发的通用接口限流。
算法对比
| 算法 | 特点 | 问题/适用场景 |
|---|---|---|
| 固定窗口 | 实现简单,按窗口计数 | 窗口边界可能瞬间通过双倍流量 |
| 滑动日志 | 记录每次请求时间,精确 | 内存成本高 |
| 滑动窗口计数 | 多小格近似统计 | 精度与成本可调 |
| 漏桶 | 恒定速率流出,流量平滑 | 对突发不友好,适合保护稳定下游 |
| 令牌桶 | 恒速产令牌,可积累后应对突发 | 需设速率和桶容量 |
面试口语版
限流前先根据压测确定系统安全容量,再选择作用范围:单机可用内存令牌桶,分布式可由网关结合 Redis Lua 做原子限流。维度可以是接口、用户、租户、IP 或业务优先级。超过阈值后不只是返回 429,还可以排队、降级、使用缓存或丢弃低优先级任务。限流必须配合监控,否则阈值错误会把正常流量误杀。
关键细节
- 分布式限流要权衡强一致和性能,本地限流配合集中配额下发常更稳健。
- 限流放在越靠前的位置,节省的后端资源越多;核心服务仍要做自保护。
- 重试请求也消耗容量,客户端应遵循
Retry-After并指数退避。
面试官追问
- Redis 如何原子实现令牌桶?
- 网关宕机或 Redis 不可用时 fail-open 还是 fail-close?
- 如何设计动态限流?
面试官追问参考答案
1. Redis 如何原子实现令牌桶?
Key 保存当前令牌数和上次补充时间。Lua 脚本根据当前时间计算应补令牌数,取不超过桶容量的值,再判断是否足够消费并更新状态,整个过程单 Key 原子执行;还要设置过期时间,避免长期不用的桶占内存。
2. 网关宕机或 Redis 不可用时 fail-open 还是 fail-close?
取决于业务风险。登录浏览等低风险接口可 fail-open 并启用单机保底限流,保证可用性;支付、资金、库存等高风险接口宜 fail-close 或进入严格降级,避免突破硬约束。策略要按接口分级,不能全局固定。
3. 如何设计动态限流?
以压测容量为静态上限,再根据 CPU、延迟、错误率、线程池排队和下游健康动态调整配额。可用 AIMD 或自适应并发限制,下降要快速、恢复要缓慢并设上下界和迟滞,配置通过控制面下发,数据面保留本地兜底。