高并发到底是什么?从 QPS、并发数到响应时间
什么才叫高并发?
很多时候我们会看到:
支持 1000 并发
支持 10000 QPS
支持百万级并发
这些数字看起来很直观,但实际上:
1000 并发
1000 QPS
1000 个连接
1000 TPS
完全不是同一个概念。
如果不区分这些指标,就很容易在性能测试和系统设计中得出错误结论。
1. “高并发”到底是什么意思?
“高并发”并不是一个严格固定的数字。
例如:
1000 QPS
对于一个简单的内部管理系统,可能已经非常高。
但对于大型互联网服务,这个数字可能非常普通。
因此:
高并发是相对于系统规模、业务模型和资源能力而言的概念,而不是一个固定阈值。
更准确地说,高并发关注的是:
大量请求
↓
在较短时间内
↓
同时进入系统
↓
系统仍然能够稳定处理
这里至少涉及三个维度:
请求到达速度
请求同时存在的数量
请求完成速度
对应到性能指标,就是:
QPS / RPS
并发数
响应时间 / 吞吐量
因此,讨论高并发时,不能只说:
“我们的系统能扛 10 万并发。”
还应该继续问:
什么类型的请求?
多少 QPS?
平均 RT 多少?
P99 多少?
请求是否访问 MySQL?
数据库连接池多大?
CPU 利用率多少?
内存多少?
否则这个“10 万并发”几乎没有实际意义。
2. 并发数:现在有多少请求正在进行?
并发数(Concurrency)描述的是:
某个时间点或者某个时间窗口内,同时处于处理过程中的任务数量。
例如:
14:00:00
↓
请求 A
请求 B
请求 C
请求 D
此时如果这 4 个请求都还没有完成:
Concurrency ≈ 4
需要注意:
并发数不是每秒请求数量。
例如:
系统当前有 100 个请求正在处理
表示:
Concurrency = 100
而不是:
QPS = 100
一个简单例子
假设:
每秒进入 100 个请求
每个请求平均处理 1 秒
那么系统中大约会同时存在:
100 个请求
因此:
Concurrency ≈ 100
如果请求平均只需要:
100ms
那么:
每秒 100 个请求
平均 RT = 100ms
系统中的平均在途请求数量大约是:
100 × 0.1 = 10
也就是说:
QPS = 100
RT = 100ms
Concurrency ≈ 10
这已经说明:
QPS 和并发数不是一回事。
3. QPS 和 RPS:每秒处理多少请求?
QPS 是:
Queries Per Second
传统上经常用于描述每秒处理的查询数量。
对于 HTTP 服务,更准确、也更常见的指标之一是:
RPS(Requests Per Second)
即:
每秒处理多少个请求
例如:
RPS = 1000
可以理解为:
平均每秒完成约 1000 个请求
在 API 服务中:
GET /api/users
POST /api/orders
GET /api/products
都可以按照请求完成数量进行统计。
QPS 不是固定的“系统性能”
假设:
服务器 A
QPS = 1000
服务器 B:
QPS = 2000
不能直接得出:
B 比 A 快一倍
因为还缺少很多信息:
请求内容
CPU
内存
数据库
缓存命中率
响应大小
RT
错误率
P99
例如:
A:
1000 QPS
RT = 10ms
B:
2000 QPS
RT = 5s
如果只看 QPS,B 更高。
但从用户体验和系统稳定性来看,B 未必更好。
所以性能测试一定不能只看 QPS。
4. TPS:它和 QPS 有什么区别?
TPS 是:
Transactions Per Second
即:
每秒完成多少个事务
它更多用于具有明确“事务”概念的场景。
例如:
支付
订单
数据库事务
金融交易
假设一次用户下单操作:
创建订单
↓
扣库存
↓
创建支付记录
如果整个过程被业务定义为一个 Transaction,那么:
TPS = 每秒完成的交易数量
而 QPS/RPS 更偏向:
Query / Request
因此:
QPS ≠ TPS
两者的具体含义取决于系统的统计口径。
例如一个订单交易可能涉及:
1 个 HTTP 请求
↓
5 次 SQL
↓
2 次 Redis 操作
↓
1 次 RPC
那么:
HTTP RPS = 1000
并不意味着:
SQL QPS = 1000
Redis QPS = 1000
RPC QPS = 1000
真实系统中,一个上游请求可能放大成多个下游操作。
这个问题在下一篇“HTTP 请求的并发链路”中会重点讨论。
5. 响应时间 RT:请求到底花了多久?
RT(Response Time)表示一次请求从开始到完成所经历的时间。
例如:
Request
↓
开始:10:00:00.000
↓
完成:10:00:00.100
那么:
RT = 100ms
但生产环境不能只看平均 RT。
例如 1000 个请求:
990 个:10ms
10 个:5s
平均值可能仍然不算特别夸张。
但这 10 个用户已经明显感受到卡顿。
因此实际监控中经常关注:
P50
P90
P95
P99
P999
这些称为百分位延迟(Percentile Latency)。
例如:
P50 = 20ms
P95 = 80ms
P99 = 500ms
可以理解为:
50% 的请求 ≤ 20ms
95% 的请求 ≤ 80ms
99% 的请求 ≤ 500ms
这里的统计必须建立在明确的采样窗口和指标口径上。
因此:
平均 RT 适合观察整体趋势,但不能替代尾延迟指标。
6. Little’s Law:把并发、QPS 和 RT 串起来
这是理解高并发最重要的公式之一。
排队论中的 Little’s Law:
L = λW
其中:
L = 系统中的平均任务数量
λ = 平均到达率
W = 平均停留时间
放到 HTTP 服务中,可以近似理解为:
平均并发数
≈
平均 RPS × 平均响应时间
例如:
RPS = 1000
RT = 100ms
因为:
100ms = 0.1s
所以:
Concurrency
≈
1000 × 0.1
≈
100
也就是说:
1000 RPS
100ms RT
系统中平均大约有:
100 个在途请求
如果 RT 变成 1 秒
还是:
RPS = 1000
但:
RT = 1s
那么:
Concurrency
≈
1000 × 1
≈
1000
并发数量从:
100
增加到:
1000
如果 RT 变成 10 秒
那么:
Concurrency
≈
1000 × 10
≈
10000
此时:
RPS 没变
但是:
在途请求
100 → 10000
增加了 100 倍。
这就是高并发系统中非常重要的一个现象:
系统变慢以后,即使流量没有增加,并发数也可能快速增加。
7. 为什么请求变慢会导致系统雪崩?
假设系统正常情况下:
RPS = 1000
RT = 100ms
因此:
平均并发 ≈ 100
现在 MySQL 出现问题:
SQL RT
100ms → 2s
整个 HTTP 请求:
RT
100ms → 2s
那么:
平均并发
≈
1000 × 2
=
2000
系统中的在途请求从:
100
增加到:
2000
接下来可能出现:
请求增加
↓
数据库变慢
↓
HTTP RT 增加
↓
在途请求增加
↓
连接池被占满
↓
请求排队
↓
RT 进一步增加
↓
更多请求堆积
最终形成:
下游变慢
↓
请求堆积
↓
资源耗尽
↓
系统进一步变慢
这就是为什么高并发系统不仅要关注:
CPU
QPS
还必须关注:
RT
连接池
队列长度
超时
资源利用率
8. 并发数、连接数和 QPS 不能混为一谈
这几个概念在实际开发中非常容易混淆。
并发请求
当前正在处理的请求数量
例如:
1000 个请求正在等待完成
可以说:
约 1000 并发请求
TCP 连接数
当前建立的 TCP 连接数量
例如:
10000 TCP Connections
并不意味着:
10000 个请求正在执行
因为一个 TCP 连接可能:
空闲
保持 Keep-Alive
正在传输请求
正在传输响应
HTTP/1.1 可以在连接上复用多个请求,但具体是否以及如何复用取决于连接状态和协议行为;HTTP/2 则可以在一个连接上并发承载多个 Stream。
所以:
连接数 ≠ 请求并发数
QPS
表示:
单位时间内完成多少请求/查询
所以:
Connections
Concurrency
QPS
分别描述:
连接规模
在途任务规模
处理速率
这是三个完全不同的维度。
9. 一个真实的性能指标应该怎么看?
假设压测得到:
RPS = 5000
Average RT = 30ms
P95 = 60ms
P99 = 120ms
CPU = 65%
Memory = 55%
Error = 0.01%
我们至少可以知道:
吞吐量:5000 RPS
平均响应时间:30ms
P99:120ms
CPU:65%
错误率:0.01%
根据 Little’s Law:
平均并发
≈
5000 × 0.03
≈
150
也就是说:
5000 RPS
30ms 平均 RT
对应平均大约:
150 个在途请求
但这仍然不能说明系统一定可以“稳定支持 5000 并发”。
因为还需要知道:
数据库情况
Redis 情况
网络带宽
连接池
最大连接数
请求分布
P99
P999
错误率
测试持续时间
尤其是压测不能只跑几秒钟。
一个短时间的峰值结果:
5000 RPS
和系统持续几十分钟甚至数小时仍然稳定:
5000 RPS
是完全不同的能力。
10. 高并发最终是在解决什么问题?
到这里,我们可以把前面的概念统一起来:
请求到达
│
▼
RPS
│
▼
在途请求数量
│
▼
并发数
│
▼
CPU / IO / 网络
│
┌─────────┼─────────┐
▼ ▼ ▼
Redis MySQL RPC
│ │ │
└─────────┼─────────┘
▼
RT
│
▼
响应
可以把几个核心指标理解成:
| 指标 | 关注的问题 |
|---|---|
| RPS / QPS | 每秒处理多少请求/查询 |
| TPS | 每秒完成多少事务 |
| 并发数 | 同时有多少任务处于进行状态 |
| RT | 一个请求需要多长时间完成 |
| P95/P99 | 尾部请求到底有多慢 |
| Connection | 当前有多少网络连接 |
| 吞吐量 | 单位时间完成多少工作 |
| Error Rate | 请求失败比例 |
这些指标共同描述一个系统的运行状态。
所以真正的高并发问题不是:
“怎么让服务器处理 10 万请求?”
而是:
在大量请求同时存在的情况下,如何让整个系统持续、稳定、可预测地完成这些请求。
这就需要考虑:
并发模型
↓
CPU
↓
IO
↓
连接池
↓
数据库
↓
缓存
↓
队列
↓
限流
↓
背压
↓
超时
↓
熔断
↓
降级
因此,高并发从来不是某一个组件的问题,而是整个请求链路的容量问题。
总结
这一篇最重要的不是记住几个指标,而是建立它们之间的关系。
首先:
并发数 ≠ QPS
并发数表示:
当前有多少任务正在进行
QPS/RPS 表示:
单位时间完成多少请求
其次:
连接数 ≠ 并发请求数
一个 TCP 连接可以处于空闲、保持连接或者承载请求等不同状态。
然后:
QPS ≠ TPS
QPS/RPS 通常描述请求或查询速率,而 TPS 更强调事务完成速率,具体含义取决于系统定义。
最重要的关系是:
平均并发数
≈
平均 RPS × 平均 RT
例如:
1000 RPS × 100ms
≈ 100 并发
如果:
1000 RPS × 5s
≈ 5000 并发
所以:
系统变慢以后,即使 QPS 没有增加,并发请求数量也可能快速增加。
这也是高并发系统容易发生级联故障的重要原因之一。
最终,可以用这样一张图理解整个系列目前建立的知识:
HTTP 请求
│
▼
Socket
│
▼
进程 / 线程 / 协程
│
▼
IO 多路复用 / Event Loop
│
▼
业务代码
│
├── CPU
├── Redis
├── MySQL
└── RPC
│
▼
响应时间 RT
│
▼
RPS / QPS
│
▼
在途请求
│
▼
并发数
到这里,我们已经分别理解了:
请求是什么
谁执行请求
如何管理大量 IO
如何衡量并发