百万 QPS(每秒百万次请求)是互联网基础设施的顶级量级,只有少数头部公司(如 Google、Meta、阿里、腾讯核心链路)在特定场景下能达到。对大多数团队来说,更现实的目标是:先设计可水平扩展的架构,再按流量阶梯逐步演进。本文挑重点讲清楚原理、分层和落地路径。
1. 百万 QPS 意味着什么
在动手之前,必须做容量建模:
| 指标 | 估算 |
|---|---|
100 万 QPS | 每秒 100 万次 HTTP 请求 |
按平均 1KB 响应 | 出站带宽约 8 Gbps(仅响应体) |
按 10ms 平均延迟 | 任意时刻约 1 万个并发连接 在处理中 |
单机极限 | 普通 Web 服务器约 1–5 万 QPS(静态/缓存命中场景) |
结论:不可能靠单机扛百万 QPS,必须依赖 CDN 边缘缓存 + 多层负载均衡 + 大规模水平扩展 + 异步解耦。
2. 整体架构
百万 QPS 的核心思路是 「让请求尽量死在离用户最近的地方」:
每一层都有明确职责,且都可独立扩容。
3. CDN 与边缘计算:第一道防线
3.1 静态资源
- HTML、CSS、JS、图片、视频走 CDN,命中率可达 95%+
- 若 100 万 QPS 中有 80 万是静态资源,CDN 吸收后,源站只剩 20 万 QPS
3.2 动态内容边缘化
- Edge Side Includes (ESI)、边缘 SSR
- Cloudflare Workers、AWS Lambda@Edge 在边缘做鉴权、A/B、限流
- 把「读多写少」的 API 做成 边缘缓存(短 TTL + 缓存键设计)
3.3 关键实践
- 合理设置
Cache-Control、ETag、Vary - 按地域部署 PoP,减少回源
- 源站保护:CDN 回源限流、源站 IP 白名单
4. 负载均衡:两层结构
4.1 四层 LB(L4)
- 基于 IP + 端口转发,性能极高
- 常用:LVS(DR/NAT 模式)、F5、云厂商 NLB
- 单台 LVS 可达 百万级连接,QPS 取决于包大小
- 多 LB 用 ECMP / Anycast / DNS 轮询 做横向扩展
4.2 七层 LB(L7)
- 基于 HTTP 路由、TLS 终止、限流、灰度
- 常用:Nginx、Envoy、HAProxy、云 ALB
- 单实例约 5–10 万 QPS(视配置而定),需要 几十到上百实例
4.3 选型建议
DNS(GSLB) → Anycast VIP → L4 LB 集群 → L7 LB 集群 → 应用 Pod
- TLS 在 L7 或专用 SSL 卸载层终止(硬件或 Envoy)
- 长连接场景注意 连接数 而非只看 QPS
5. 应用层:无状态 + 水平扩展
5.1 无状态设计
- Session 外置到 Redis 集群
- 文件上传走 对象存储(S3/OSS)
- 任意实例可随时扩缩容
5.2 容器化与编排
- Kubernetes + HPA(按 CPU/QPS/自定义指标扩缩)
- 单集群可管理数千 Pod;超大规模用 多集群 + 联邦
- 服务网格(Istio/Linkerd)做流量治理,但高 QPS 场景要评估 sidecar 开销
5.3 语言与运行时
| 场景 | 推荐 |
|---|---|
高 QPS 读接口 | Go、Rust、C++ |
复杂业务 | Java(虚拟线程/GraalVM)、Go |
计算密集 | 独立 Worker 池 |
- 连接池、对象池减少 GC 压力
- 零拷贝、io_uring(Linux)优化 I/O
- 避免同步阻塞调用链路过长
5.4 容量估算示例
假设单个 Go 实例稳态 2 万 QPS:
- 源站需扛 20 万 QPS → 约 10 台(加 50% 冗余 → 15 台)
- 多可用区部署,单区故障仍可用
6. 缓存:多层缓存体系
缓存是扛高并发最核心的手段。
6.1 浏览器缓存
max-age、immutable减少重复请求
6.2 CDN 缓存
- 见上文,吸收绝大部分流量
6.3 应用本地缓存
- Caffeine、ristretto 等进程内缓存
- 适合热点配置、字典数据,延迟 微秒级
- 注意多实例一致性:短 TTL + 发布时失效
6.4 分布式缓存(Redis)
- 单 Redis 约 10–20 万 QPS(GET,集群模式)
- 百万 QPS 读 → Redis Cluster 数十节点,或 多级缓存(本地 + Redis)
- 热点 Key:本地缓存 + 随机过期 防雪崩;互斥锁/单飞(singleflight) 防击穿
6.5 数据库查询缓存
- 缓存穿透:布隆过滤器
- 缓存雪崩:过期时间加随机抖动
- 缓存与 DB 一致性:延迟双删、订阅 binlog 失效缓存
6.6 典型读路径
请求 → 本地缓存命中? → Redis 命中? → DB(最后手段)
目标:打到 DB 的 QPS 控制在 数百~数千。
7. 数据库:读写分离 + 分片
DB 是典型瓶颈,百万 QPS 下必须 少写多读、异步写、分片存储。
7.1 读写分离
- 主库写,多个只读副本读
- 注意主从延迟,读己之写用 主库读 或 会话一致性
7.2 分库分表
- 水平分片:按 user_id、order_id 等 hash
- 中间件:ShardingSphere、Vitess、Citus(PG)
- 跨分片查询尽量避免,或走 ES/OLAP 做分析
7.3 数据库选型
| 类型 | 场景 |
|---|---|
MySQL/PostgreSQL | 事务型核心业务 |
TiDB/CockroachDB | 分布式 SQL,自动分片 |
Cassandra/ScyllaDB | 超高写入、宽表 |
DynamoDB | 云原生 KV,自动扩展 |
7.4 连接池
- 应用与 DB 之间用 PgBouncer、ProxySQL
- 避免「每个 Pod 一个连接」导致连接数爆炸
8. 异步化与消息队列
同步链路越长,能扛的 QPS 越低。
8.1 写操作异步化
用户下单 → API 快速返回「已受理」→ 消息队列 → 订单/库存/支付 Worker
- 队列:Kafka、Pulsar、RocketMQ
- Kafka 单集群可达 百万级消息/秒(分区扩展)
8.2 削峰填谷
- 秒杀、抢购:请求先入队,Worker 按 DB 能力消费
- 配合 令牌桶/漏桶限流
8.3 CQRS
- 写模型与读模型分离
- 写走 OLTP,读走 Redis / ES / 物化视图
- 最终一致性可接受时,读性能可提升一个数量级
9. 限流、熔断、降级
高并发下,保护系统比服务所有请求更重要。
9.1 多级限流
全局限流(网关)→ 服务级限流 → 接口级限流 → 用户级限流
- 算法:令牌桶、滑动窗口
- 实现:Envoy rate limit、Sentinel、自研 Redis + Lua
9.2 熔断
- 下游故障时快速失败,避免级联雪崩
- Hystrix / resilience4j / Envoy outlier detection
9.3 降级
- 非核心功能关闭(推荐、评论)
- 返回兜底数据(缓存快照、默认值)
- 静态化热点页面
10. 网络与基础设施
10.1 带宽
- 百万 QPS × 1KB ≈ 8 Tbps 级别 的峰值带宽需求(含请求+响应)
- 实际靠 CDN 边缘消化,源站带宽需求小得多
10.2 多地域部署
- Active-Active 多活:用户就近接入
- 数据:多活冲突用 CRDT、最后写入胜出、或业务层规避
10.3 专线与 Anycast
- 骨干网 Anycast 将流量导向最近数据中心
- 跨地域数据同步延迟要纳入设计
11. 可观测性:没有监控等于盲飞
百万 QPS 下,1% 错误 = 每秒 1 万次失败。
11.1 三大支柱
- Metrics:Prometheus + Thanos/Mimir,RED/USE 方法
- Logs:ELK/Loki,采样 + 结构化
- Traces:Jaeger/Tempo,分布式追踪找慢点
11.2 关键指标
- QPS、P99 延迟、错误率、饱和度
- 缓存命中率、队列积压、DB 连接池使用率
- 告警按 SLO 设定(如 99.9% 请求 < 200ms)
11.3 全链路压测
- 生产级压测:流量录制回放、影子流量
- 逐步加压,找到第一个瓶颈点
12. 安全:高并发下的 DDoS 防护
- CDN + WAF 吸收恶意流量
- 验证码、人机校验在边缘完成
- SYN Cookie、连接限速
13. 演进路径:不要一步到位
大多数系统不需要第一天就百万 QPS。建议分阶段:
| 阶段 | QPS 量级 | 典型架构 |
|---|---|---|
1 | < 1 万 | 单机/小集群 + MySQL + Redis |
2 | 1–10 万 | 多实例 + 读写分离 + CDN |
3 | 10–50 万 | 分库分表 + 消息队列 + 多级缓存 |
4 | 50–100 万+ | 多地域 + 边缘计算 + 专用基础设施 |
每一步用 压测验证瓶颈,再针对性优化,避免过度设计。
14. 常见误区
- 堆机器不堆架构:无状态、缓存、异步没做好,加机器收益递减
- 忽视热点:少数 Key 打爆 Redis 单分片,需本地缓存 + 热点探测
- 同步链路过长:一个请求串 10 个微服务,P99 必然爆炸
- 过度微服务化:百万 QPS 下服务间 RPC 开销可观,合并热点路径
- 没有压测:上线后才发现 DB 连接池、某个 JSON 序列化是瓶颈
15. 总结
支撑百万 QPS 的本质是:
- 边缘消化:CDN + 边缘计算挡住绝大部分流量
- 水平扩展:每一层无状态、可独立扩容
- 缓存为王:多级缓存,让 DB 几乎不被读流量打穿
- 异步解耦:写操作走队列,读走缓存
- 限流降级:宁可拒绝,不可雪崩
- 可观测 + 压测:用数据驱动扩容和优化
没有银弹,只有 分层、分片、缓存、异步 的组合拳。根据业务类型(读多/写多、一致性要求)调整权重,按流量阶段演进,比一开始就追求「百万 QPS 架构」更务实。