2026年7月13日 · 4 分钟阅读
高并发系统设计与限流:容量、削峰、背压和过载保护
从容量模型和分层架构出发,系统梳理缓存、消息队列、数据库扩展,以及固定窗口、滑动窗口、漏桶、令牌桶和并发限制的工程实践。
高并发设计不是罗列缓存、MQ、分库分表,而是让系统在目标流量和故障条件下仍满足延迟、可用性与成本约束。
先建立容量模型
并发数 ≈ 到达速率 × 平均响应时间
安全吞吐 = min(入口、应用、下游、数据库的可持续能力)
平均值不足以规划系统,还要看峰值、P95/P99 延迟、请求大小、热点分布和突发持续时间。先用压测找到最窄瓶颈,再决定扩容或架构改造。
分层扩展
- CDN、静态化和本地缓存减少请求进入核心系统。
- 无状态应用水平扩展,连接池和线程池必须有界。
- Redis 承载热点读,但要治理穿透、击穿和一致性。
- MQ 将非关键链路异步化并吸收短期峰值。
- 数据库先优化索引和 SQL,再读写分离、垂直拆分和水平分片。
- 熔断、降级、隔离和限流防止局部故障级联。
每加一层都引入新失败模式。系统图要同时画正常数据流和超时、重试、回退、积压路径。
限流算法
| 算法 | 原理 | 特点 |
|---|---|---|
| 固定窗口 | 每个时间窗口计数 | 简单,但窗口边界可能放过双倍突发 |
| 滑动日志 | 保存窗口内每次请求 | 精确,内存和维护成本高 |
| 滑动计数 | 多个小桶加权统计 | 精度与成本折中 |
| 漏桶 | 请求以固定速率流出 | 输出平滑,但不善于利用允许突发 |
| 令牌桶 | 按速率补充令牌,请求消耗令牌 | 可限制长期速率并允许桶容量内突发 |
| 并发限制 | 限制同时执行数 | 直接保护线程、连接等稀缺资源 |
流量速率正常但下游变慢时,QPS 限制可能仍保护不足;并发限制会随处理时间上升更早触发,因此两者常组合使用。
限流放在哪里
入口网关做租户、IP、接口级粗粒度限制;服务内部按业务键和下游依赖细分;数据库、线程池和连接池还需要资源隔离。越靠前拒绝成本越低,越靠后越了解业务价值。
分布式限流可用 Redis Lua 原子执行令牌桶或滑动窗口,但 Redis 故障时必须预先选择 fail-open 还是 fail-closed。支付和安全接口可能宁可拒绝,普通内容接口可能允许受控放行。
被限制后怎么办
限流不是返回 429 就结束:
- 响应包含明确错误码与可选
Retry-After。 - 客户端使用指数退避和随机抖动,禁止立即无限重试。
- 核心请求保留独立配额,非核心功能降级。
- 异步任务可进入有界队列,但队列满后必须拒绝或丢弃低价值任务。
- 记录限流维度、规则版本和业务影响,支持动态调整。
背压与自适应保护
静态阈值来自压测,真实容量会随下游延迟和资源变化。可以根据在途请求、延迟、错误率和队列长度动态降低并发。但自适应算法也会振荡,应设置平滑、上下限和恢复步长。
重试会放大流量。一次请求跨三个下游、每层重试三次,最坏调用数可能指数增长。重试应只在最合适的一层发生,并受总时间预算和次数限制。
可观测性与演练
监控入口 QPS、通过/拒绝量、在途并发、队列长度、P95/P99、超时、重试、下游饱和度和业务成功率。压测要覆盖阶梯加压、突发流量、热点键、下游变慢和节点故障,找出系统进入排队崩溃前的拐点。
工程检查清单
- SLO、峰值、突发持续时间和容量余量有明确数字。
- 限流按租户、业务优先级和下游资源分层。
- 线程池、连接池、队列和重试都有上限。
- 被限流后的降级、响应和客户端退避已定义。
- Redis/MQ/数据库故障时有受控回退,而非无限放量。
- 定期通过压测和故障演练校准阈值。
面试回答要点
回答高并发设计时,先给容量和 SLO,再从减少请求、水平扩展、缓存、异步削峰、数据库扩展和稳定性保护展开。讲限流时对比窗口、漏桶、令牌桶和并发限制,并补充限流位置、分布式原子性、失败策略和拒绝后的降级。
总结
高并发系统的核心是控制排队和资源竞争。缓存与扩容提高容量,MQ 平滑短峰,限流、并发控制和背压则在容量不足时保护系统。只有拒绝和恢复路径同样清晰,系统才真正具备过载稳定性。