Skip to content

高并发读架构 — 百万 QPS 怎么扛

系统设计 ⭐⭐⭐ 进阶 🔥🔥🔥 必考

💡 核心要点

高并发读的核心心智模型是「全链路逐级削峰」:CDN 挡 50%、网关挡 20%、本地缓存挡 20%、Redis 挡 9%、数据库只剩 1%。任何"百万 QPS 读"的题目,先把这五层画出来,再分别讲每层的方案与瓶颈,就是面试满分答案。

这页解决什么问题

面试题:

  • "设计商品详情页,单 SKU 100w QPS 怎么办?"
  • "设计微博热搜,热点话题瞬时 50w QPS 怎么办?"
  • "春运抢票,余票查询接口要扛 200w QPS"
  • "设计 Twitter 个人主页" / "抖音 Feed 推荐流"

这一类题统称"高并发读"——共同特征是读多写少(读写比 1000:1 甚至更高),允许短时间不一致(秒级)。处理思路高度同构:全链路逐级削峰 + 多级缓存

全链路架构总览

                ┌──────────┐
                │   用户   │
                └────┬─────┘
                     │ 100w QPS

              ┌─────────────┐
        ① CDN │  CDN 边缘    │  挡 50% → 剩 50w QPS
              │ (Cloudflare/└─┐
              │  Cloudfront)  │
              └─────────────┘ │ 50w

                    ┌──────────────┐
              ② LB  │   负载均衡    │ 流量分发 + 健康检查
                    │ (Nginx/LVS)   │
                    └──────┬───────┘

                    ┌──────────────┐
              ③ GW  │   API 网关    │ 鉴权 + 限流,挡 20% → 剩 30w
                    │ (Kong/Envoy)  │
                    └──────┬───────┘

                    ┌──────────────┐
              ④ APP │ 应用服务集群  │ 100 台 × 3000 QPS
                    └──────┬───────┘

              ┌────────────┼────────────┐
              ▼            ▼            ▼
        ┌─────────┐  ┌─────────┐  ┌─────────┐
   ⑤ L1 │ Caffeine │  │ Caffeine │  │ Caffeine │  本地缓存
        │ (各机)   │  │          │  │          │  挡 20% → 剩 10w QPS
        └────┬────┘  └────┬────┘  └────┬────┘
             └──────────┬─┘────────────┘

                  ┌──────────┐
              ⑥ L2│  Redis   │ 集群 / 分片
                  │ Cluster  │ 挡 9% → 剩 1w QPS
                  └────┬─────┘

                  ┌──────────┐
              ⑦ DB│  MySQL   │ 主 + N 个只读副本
                  │ (RW+R*N) │ 剩 1% = 1w QPS
                  └──────────┘

金句:「用户能从下游走到 DB 是失败,能在上游被挡住是成功」。

每层方案与瓶颈

① CDN — 静态资源 / 半动态内容的第一道墙

适用:图片、CSS、JS、视频、静态化的 HTML

关键能力

  • 边缘节点缓存(全球数千节点,用户就近访问)
  • Pull / Push 模式:Push 主动预热(618 大促)、Pull 按需回源
  • 缓存 TTL 控制:静态资源年级别,半动态分钟级
  • 回源率监控:理想 < 5%

深入做法:商品详情页"静态化 HTML"——把动态接口聚合后生成 HTML 推到 CDN,冷启动后 99% 流量根本不到源站。京东、淘宝商品详情页用了 15 年这套架构。

何时不能用

  • 个性化内容(首页推荐流)—— 改用 ESI / Edge Workers 动态拼装
  • 必须实时数据(库存)—— 单独走 API 不走 CDN

详见 CDN 与负载均衡

② 负载均衡 — 把流量摊到 N 台机

两层架构(生产标配)

LVS(L4,硬件级,单机 1000w QPS)
  → Nginx(L7,单机 10w QPS,做 HTTPS 卸载 / URL 路由)
    → 应用服务(单机 3000 QPS)

核心算法

  • 轮询 / 加权轮询:通用
  • 一致性哈希:让同一用户落到同一机器,提升本地缓存命中率
  • 最少连接:长连接场景

单点防护:Nginx 必须主备 + Keepalived VIP,否则就是单点故障。

③ API 网关 — 限流 / 鉴权 / 兜底

网关能挡的流量

  • 限流:单用户 / 单 IP / 接口级(令牌桶或滑动窗口,详见 限流与熔断
  • 熔断:下游异常时直接返回降级值(如默认推荐列表)
  • 鉴权 / 黑名单:恶意流量提前剔除
  • 降级:非核心接口直接返回兜底值(如商品详情拿不到评论时返回空列表)

生产案例:双 11 大促,网关层会预先把"读取详情" 这类核心接口限到 100w QPS 兜底,其它非核心接口直接降级——保大放小

④ 应用层 — 横向扩展 + 无状态

单机能扛多少

应用类型单机 QPS(简单读)
传统 Java 同步阻塞1000-3000
Java 虚拟线程(JDK 21+)5000-10000
Spring WebFlux / 响应式10000-30000
Go / Rust 异步20000-50000
Nginx + Lua / OpenResty50000+

横向扩展 = QPS / 单机能力:100w QPS / 3000 = 333 台。前提是无状态(session 放 Redis,不放本地)。

进阶优化

  • 同 region 部署、跨 AZ 容灾(防地震 / 机房断电)
  • 用 K8s HPA 按 CPU / QPS 自动扩缩容

⑤ L1:本地缓存 — 最后一公里减压

为什么需要 L1:每次请求查 Redis 都有网络往返(1-2ms)+ 序列化反序列化(~0.5ms)。100w QPS 时 Redis 集群带宽 / CPU 顶不住。L1 本地缓存命中即 0 延迟

主流方案

算法单机 QPS
CaffeineW-TinyLFU1000w+(高命中率)
Guava CacheLRU100w
ConcurrentHashMap + 手写 LRULRU1000w

致命陷阱L1 一致性——商品价格改了,N 台机器各自的 L1 怎么同步?

方案 A(最常用):短 TTL(1-10s),可接受秒级不一致
方案 B:发布订阅,写操作后广播失效(Redis Pub/Sub / Kafka)
方案 C:版本号 + 主动失效(业务侧通知)

详见 缓存策略 — 多级缓存

⑥ L2:分布式缓存 — Redis 集群

Redis 单实例:约 8w QPS(CPU 单线程瓶颈)

Redis Cluster 16 分片:约 128w QPS(线性扩展)

热点 Key 问题:单个 key 100w QPS 时,单分片承受不住(详见 热点 Key 与幂等性

解法

  1. Key 拆分stock:item_999stock:item_999:shard_0..N,N 个分片各承担 1/N
  2. 本地缓存兜底:用 L1 把单机热点流量吃掉
  3. 多副本读分流:用 Redis 读写分离(主写从读)

⑦ 数据库 — 读写分离 + 副本扩展

主库写 + N 个从库读

       App

   ┌────┴────┐
   ▼ 写       ▼ 读
 Master  ─── Slave1 (读)
         ─── Slave2 (读)
         ─── Slave3 (读)  ← 扩展只读副本应对读流量

主从同步延迟:MySQL 异步复制通常 < 1s,但读副本可能拿到旧值。3 种处理

  • 容忍延迟(推荐:90% 业务可接受)
  • 强一致读直接走主库(金融场景)
  • 读写分离中间件:Sharding-Sphere、MyCat、TiDB

单库瓶颈:单 MySQL 极限 ~ 5w QPS。再大要分库分表(详见 存储选型)。

流量估算速查表

面试时心算用:

维度单机 / 单组件能力
CDN 单节点100w+ QPS(边缘节点)
Nginx 反向代理5-10w QPS(L7)
LVS(DR 模式)1000w+ QPS(L4)
应用服务(Java 同步)1000-3000 QPS / 单机
应用服务(Go / Rust)2-5w QPS / 单机
Caffeine 本地缓存1000w QPS(无网络)
Redis 单实例8-10w QPS
Redis Cluster 16 分片~128w QPS
MySQL 单库3-5w QPS
千兆网卡12w QPS(1KB / 请求)
万兆网卡120w QPS

口诀:「Redis 8w、MySQL 5w、Caffeine 千万」。

典型案例剖析

案例 1:商品详情页 100w QPS(淘宝/京东)

架构

用户 → CDN(静态化 HTML,命中 95%)→ Nginx → 应用 → L1 Caffeine(命中 90%) → Redis Cluster → MySQL

逐级削峰

流量命中率 / 通过率剩余流量
用户100w QPS100w
CDN100w命中 95%5w
应用 + L1 Caffeine5w命中 90%5000
Redis Cluster5000命中 99%50
MySQL500(实际几乎没流量到 DB)

关键设计

  1. 商品信息静态化:每次商品改价 → 触发 CDN 刷新(秒级生效)
  2. 价格 / 库存单独走 API:不进 HTML,走 Redis(这部分扛大头)
  3. L1 短 TTL:5s,可接受小不一致

案例 2:微博热搜瞬时 50w QPS

特点:热点突发、读冷启动后变热

架构

用户 → CDN(半动态,TTL 30s)→ 网关(限流)→ 应用 + L1 → Redis(热搜 ZSet)→ DB(兜底)

Redis 热点 Key 拆分:热搜榜 ZSet 在多个 key 上做副本(hotsearch:rank:0..9),读时随机选一个,单 Redis 节点压力降到 1/10。

案例 3:春运抢票余票查询 200w QPS

12306 早年崩溃就是因为没做这一层架构。新架构:

用户 → CDN(车次基础信息)→ 网关 → 应用 + L1(5s TTL)→ Redis(余票数)→ Order DB(实际订单数据)

核心 trick

  • 余票查询和下单完全分离:查询走 Redis,下单走 DB
  • L1 短 TTL 5s 可接受:用户看到的余票数允许 5 秒延迟(看到有票点进去发现没了,重新查即可)
  • 下单串行化保证一致:下单时走 DB 行锁 / 乐观锁,确保不超卖

跟其他章节的关联

子主题详细页面
多级缓存细节、Cache Aside / Write Through / Write Behind缓存策略
限流算法(令牌桶 / 漏桶 / 滑动窗口)限流与熔断令牌桶/漏桶手撕
热点 Key 5 种解法幂等性与热点 Key
Caffeine W-TinyLFU 内部原理LFU 缓存
CDN 边缘节点 / 一致性哈希CDN 与负载均衡
数据库读写分离 / 分库分表存储选型MySQL 分库分表
Redis Cluster 分片Redis
Bloom Filter 防穿透哈希表 — Bloom Filter

面试常问 & 怎么答

"百万 QPS 读怎么扛"

七层削峰口诀:「CDN 50%、网关 20%、L1 20%、L2 9%、DB 1%」。 画出全链路架构图 → 逐层讲方案 → 给数字(每层挡多少、单机能力多少、横向扩多少台)。

CDN 怎么缓存动态内容

  • 静态化:把动态接口聚合后生成 HTML 推到 CDN(商品详情、文章页)
  • ESI(Edge Side Includes):CDN 边缘动态拼装碎片
  • Edge Workers:Cloudflare Workers / Fastly Compute@Edge 在边缘跑业务代码

L1 本地缓存的"一致性"怎么保证

3 个档位:

  1. 短 TTL(最常用):5-10s,业务接受秒级不一致
  2. 广播失效:写操作通过 Redis Pub/Sub / Kafka 广播到所有节点
  3. 版本号校验:每次读校验版本,过期主动拉取

电商详情页几乎全用方案 1,因为方案 2/3 的成本超过价值。

Redis 集群带宽不够怎么办

3 种解法

  • L1 兜大头:让 Caffeine 吃 80% 流量,Redis 只服务 20%
  • 拆 key:热点 key 拆 N 份(详见 热点 Key
  • Read Replica:Redis 7.2+ 支持读副本,主写从读

"强一致读"怎么处理

90% 业务能接受秒级不一致(多看个旧价格不算大事)。金融 / 库存 / 风控这类必须强一致:

  • 读必须走主库
  • 不进 L1 缓存
  • 用乐观锁 / 悲观锁兜底

看到什么就先想到这类

  • "百万 QPS 读 / 读多写少" → 七层削峰架构
  • "商品详情页 / 个人主页" → CDN + 多级缓存
  • "热搜 / Feed 推荐流" → Redis 热点 Key 拆分 + L1
  • "春运抢票余票查询" → 查询 / 下单分离,余票走 Redis
  • "为什么淘宝双 11 不崩" → 全链路削峰 + 容量预案 + 限流降级

写流量(秒杀、抢单、发帖、消息推送)有不同的架构思路,见 高并发写架构