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 平滑短峰,限流、并发控制和背压则在容量不足时保护系统。只有拒绝和恢复路径同样清晰,系统才真正具备过载稳定性。

参考资料