免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

QPS、TPS与吞吐量:系统性能的三大核心指标解析

QPS、TPS与吞吐量:系统性能的三大核心指标解析 1. 这三个词不是玄学是系统能力的“血压计”和“心率仪”刚入行那会儿我常听老同事说“这接口TPS上不去”“压测QPS崩了”“吞吐量卡在500就打不动”当时只觉得是黑话连篇。直到自己第一次独立负责一个订单结算模块的性能调优凌晨三点盯着监控面板上跳动的数字发呆——明明代码逻辑没改数据库连接池也调大了可并发一上来响应时间就从200ms直线飙到2秒错误率瞬间破15%。翻日志、查慢SQL、看线程堆栈折腾半天毫无头绪。最后发现问题根本不在代码而在对这三个基础指标的理解偏差我把“每秒处理1000个请求”当成硬性目标却没意识到这个“1000”到底是QPS还是TPS它背后对应的是用户点击下单的“动作”还是下单成功后扣减库存、生成支付单、发通知的“事务链路”更关键的是这个数字是在什么资源水位下跑出来的CPU 30%时的1000和CPU 95%时的1000价值天壤之别。TPS、QPS、吞吐量这三个词绝不是教科书里干巴巴的定义它们是系统真实运行状态的“生命体征”。QPSQueries Per Second衡量的是入口流量的脉搏频率就像医院门口的叫号机每秒叫出多少个号TPSTransactions Per Second则是业务价值的完成度刻度它不关心你叫了多少号只关心最终有多少人真正完成了挂号、问诊、开药这一整套流程而吞吐量Throughput是个更宽泛的“总产出”概念它不绑定单位时间而是聚焦于系统在特定约束下能稳定交付的总量比如“单次压测周期内成功处理10万笔订单”。很多人混淆它们本质是混淆了“输入”、“有效输出”和“总产能”这三个不同维度。搞不清这个所有性能优化都是蒙眼拉磨——你可能把叫号机调得飞快QPS飙升但诊室只有两个医生TPS上不去最后大厅挤满人吞吐量受限还误以为是叫号机坏了。这篇文章就是帮你把这三根“生命体征监测线”从监控图表里拎出来看清它们各自代表什么、怎么测、怎么解读、为什么经常打架以及当它们同时报警时你该先摸哪个“脉”。2. 核心概念解剖从字面到骨髓的三层穿透2.1 QPS流量入口的“计数器”但计什么数很关键QPS每秒查询数听起来最直白实则陷阱最多。它的核心在于“Query”这个词——到底什么是“一次查询”这个定义权完全在你手里也直接决定了QPS数字的含金量。最窄口径推荐用于网关/负载均衡层一次完整的HTTP请求。无论GET还是POST无论返回200还是500只要请求抵达你的反向代理如Nginx或API网关就算1次QPS。这是最客观、最不易被业务逻辑干扰的统计方式反映的是网络层的接入能力。某次压测中我们看到Nginx日志显示QPS稳定在8000但后端应用日志里只有4000条有效请求记录差额全是404和401错误。这说明前端路由配置有误大量无效流量冲垮了网关此时盯着8000这个数字优化后端毫无意义。中间口径常用在业务API层一次成功的、有业务意义的API调用。通常指返回HTTP状态码2xx的请求。这比网关层更贴近业务但它依然不关心这个“成功”背后做了多少事。比如一个“提交订单”API它可能内部调用了库存服务、优惠券服务、支付服务三次远程调用但对外只算1次QPS。这就引出了关键点QPS高不等于系统忙它可能只是“轻量级”的入口验证QPS低也不等于系统闲它可能卡在某个重IO操作上导致请求堆积。最宽口径需谨慎使用将一次用户操作拆解为多个子请求后的总和。例如一个网页加载浏览器可能发起1个HTML请求、3个JS请求、2个CSS请求、5个图片请求共11次HTTP请求。如果按此计算QPS11。这种算法在分析前端性能时有用但绝对不能用于评估后端服务容量因为它把客户端行为和服务器能力混为一谈。提示在做性能基线或容量规划时务必明确QPS的统计口径并在所有报告中注明。我见过太多团队因为口径不一致导致A组说QPS达标了B组说根本没达到吵了半天才发现一个算网关日志一个算应用成功日志。2.2 TPS业务价值的“验收官”必须定义清楚“一笔事务”TPS每秒事务数是这三个指标里业务价值最直接的体现者也是最容易被滥用的一个。它的灵魂在于“Transaction”——什么才算“一笔事务”这个定义必须由业务方拍板技术只是执行者。经典ACID事务数据库层面在单库场景下TPS常等同于数据库每秒提交COMMIT的事务数。一个转账操作包含“扣A账户”、“加B账户”、“写日志”三个SQL必须在一个数据库事务里完成成功提交才算1 TPS。这是最严格、最无歧义的定义但仅适用于强一致性要求极高的核心交易系统如银行核心账务。业务事务Saga模式/最终一致性现代分布式系统中跨服务的长流程如下单无法用单库事务保证。此时TPS应定义为一个完整业务流程的成功闭环。以电商下单为例TPS1意味着用户点击“提交订单”→ 库存预占成功 → 订单创建成功 → 支付单生成成功 → 用户收到下单成功通知这一整条链路上所有环节均成功。任何一个环节失败如库存不足、支付单创建超时都不计入TPS。这才是老板和产品经理真正关心的数字——它代表每秒有多少真实订单诞生。常见误区把“下单接口的QPS”直接当作“下单TPS”。这是致命错误。下单接口QPS1000可能其中200次因库存不足返回失败100次因支付服务超时失败实际成功下单的只有700笔那么TPS700。如果你只盯着QPS优化可能会去提升接口的响应速度但真正的瓶颈可能在库存服务的并发扣减能力上。注意定义TPS时必须同步定义“成功”的标准。是只要订单表写入就算成功还是必须支付单也生成或是用户收到短信才算这个标准一旦定下所有压测、监控、告警都必须以此为准。我们曾因“成功”定义模糊在大促前夜发现监控告警阈值设错了——把“订单创建成功”当TPS而业务方要求的是“支付成功”导致大促期间大量未支付订单涌入库存被虚占险些造成资损。2.3 吞吐量系统能力的“总成绩单”脱离时间谈吞吐是耍流氓吞吐量Throughput是一个更宏观、更务实的概念。它不强调“每秒”而是关注在给定条件下系统能稳定交付的总工作量。它的价值在于剥离了瞬时波动反映的是系统的“持续作战能力”。时间窗口绑定吞吐量必须和时间窗口强关联。说“系统吞吐量是10万”毫无意义必须说“在60分钟压测周期内系统稳定处理了10万笔有效订单错误率0.1%”。这个“60分钟”很关键它模拟了真实业务的持续压力而非几秒钟的峰值冲击。稳定性是前提吞吐量不是峰值冲刺而是马拉松配速。一个系统可能在1秒内扛住5000 TPS但30秒后就崩溃它的吞吐量依然是0——因为它无法“稳定”交付。所以吞吐量测试Stability Test的核心指标是在目标吞吐量下系统各项资源CPU、内存、磁盘IO、网络带宽是否持续处于安全水位如CPU75%响应时间P95是否稳定在SLA要求内如500ms错误率是否可控如0.5%。与QPS/TPS的关系吞吐量 平均QPS或TPS × 时间窗口。但它比简单的乘法深刻得多。例如一个系统在10分钟内前2分钟QPS2000峰值中间6分钟QPS800平稳最后2分钟QPS100衰减总处理量2000×120 800×360 100×120 516,000。它的平均QPS516,000 / 600 860但它的有效吞吐量应是800因为只有在这个水平下系统才表现出长期稳定性。这就是为什么容量规划要基于吞吐量而非峰值QPS——峰值是烟花吞吐量才是日常烟火气。3. 实操指南如何精准测量、对比与归因3.1 测量工具链从“看到”到“看懂”的四步法测量不是简单地跑个JMeter脚本然后截图。一套可靠的测量流程必须覆盖数据采集、清洗、聚合、归因四个环节。源头埋点Instrumentation这是精度的基石。在代码关键路径埋点而非依赖外围监控。QPS在Web框架的统一入口拦截器如Spring MVC的HandlerInterceptor中对每个请求开始和结束打点记录requestId、uri、status、startTime、endTime。避免在Controller方法里埋点因为异常可能绕过它。TPS在业务事务的“终点”埋点。例如在订单服务的createOrder()方法成功返回前记录一条order_created_success事件包含orderId、userId、amount、timestamp。确保这个埋点在事务提交之后如用TransactionalEventListener监听AFTER_COMMIT事件。吞吐量无需额外埋点它是QPS/TPS在时间窗口上的积分。但需要确保QPS/TPS的埋点数据能被可靠持久化如写入Elasticsearch或专用时序数据库InfluxDB。数据采集与传输避免日志文件解析这种低效方式。采用OpenTelemetry SDK将埋点数据以OTLP协议实时上报到Collector如Jaeger或Zipkin。Collector负责采样、过滤、格式转换再推送到后端存储。这样做的好处是数据结构化、低延迟、支持链路追踪为后续归因打下基础。聚合与可视化用Grafana对接后端存储构建核心仪表盘。QPS仪表盘按uri分组展示count(status2xx) / 60s每分钟QPS叠加count(status5xx) / 60s错误QPS。关键看两者比值。TPS仪表盘单独一个Panel展示count(eventorder_created_success) / 60s每分钟TPS并叠加其P95响应时间曲线。吞吐量仪表盘一个大数字显示“过去60分钟累计TPS”下方小字标注“当前P95: xxx ms, 错误率: x.x%”。这个数字要和容量规划文档里的目标值放在一起对比。归因分析Root Cause Analysis当TPS骤降时不能只看TPS数字。要联动分析查看对应时间段的QPS是否同步下降如果是问题在入口如DNS故障、CDN回源失败。如果QPS不变甚至上升但TPS暴跌说明大量请求在后端失败。此时看错误QPS仪表盘定位是哪个uri的5xx暴增。进入链路追踪系统随机抽取几个失败的requestId查看其完整调用链。是卡在数据库还是某个下游服务超时还是线程池耗尽这才是真正的归因。实操心得我们曾遇到TPS从1200跌到300QPS却保持1500的诡异现象。通过链路追踪发现90%的请求都在调用“优惠券核销”服务时超时5s。进一步排查发现该服务的Redis连接池被一个未关闭的连接泄漏耗尽。修复连接池配置后TPS瞬间恢复。如果没有链路追踪和精确的埋点这个问题可能要花几天才能定位。3.2 对比分析为什么“我的QPS比他高TPS却比他低”单纯比较两个数字没有意义必须放在同一套“标尺”下。以下是几个关键对比维度对比维度关键问题实例说明环境一致性是否在同一套硬件、同一版本代码、同一数据集、同一压测脚本下进行A团队用8核16G机器测QPS5000B团队用16核32G机器测QPS4000。这对比毫无价值。数据集规模压测数据是100条模拟数据还是100万真实脱敏数据数据分布如热点用户是否一致用100条数据测缓存命中率99%TPS虚高用100万数据测缓存失效TPS腰斩。业务逻辑复杂度“获取用户信息”接口的QPS和“生成年度财务报表”接口的QPS能直接比吗前者QPS10000后者QPS5但后者TPS5代表完成了5份复杂报表价值远超前者。成功率基准QPS/TPS的统计是否都基于“成功率99.5%”的前提A系统QPS2000成功率95%B系统QPS1800成功率99.9%。B系统更健康。注意永远不要脱离“成功率”和“响应时间”谈QPS/TPS。一个QPS10000但错误率20%、P955s的系统其业务价值远低于一个QPS8000、错误率0.1%、P95200ms的系统。我们内部有个铁律“三指标一体看”——任何性能报告必须同时呈现QPS、TPS、P95、错误率四个数字缺一不可。3.3 归因实战从“数字报警”到“代码修复”的完整路径当监控告警响起TPS跌破阈值下面是我总结的标准化排查路径已迭代十几次覆盖95%的常见问题第一层确认告警真实性立即登录Grafana检查TPS、QPS、错误率、P95是否同步异常。如果只有TPS掉QPS和错误率正常大概率是埋点逻辑错误如TPS埋点漏了某些成功分支先检查代码。第二层隔离入口与出口查看网关层QPS如果网关QPS也掉了问题在外部如上游调用方限流、DNS问题、DDoS攻击。如果网关QPS正常但应用层QPS暴跌问题在应用自身如JVM Full GC频繁线程池被打满OOM被K8s重启。第三层聚焦失败请求在日志系统如ELK中搜索status:5*或error:*按uri分组找出错误率最高的Top 3接口。对这些接口查看其P95和P999响应时间曲线看是否同步飙升。如果是说明是性能瓶颈如果响应时间正常但错误率高说明是业务逻辑异常如空指针、参数校验失败。第四层深挖调用链选取一个失败的requestId在链路追踪系统中打开完整调用链。重点关注耗时最长的Span是数据库查询是HTTP远程调用是本地计算失败的Span哪个环节返回了5xx或timeout并发数该Span在失败时间段内的并发请求数是否激增第五层验证与修复定位到具体问题如“MySQL查询order表user_id索引缺失”在预发环境复现并验证修复方案如添加索引。修复后用相同脚本压测确认TPS、P95、错误率全部回归基线。踩过的坑有一次TPS暴跌链路追踪显示所有请求都卡在“发送邮件”服务上。我们以为是邮件服务挂了结果发现是开发为了调试把邮件发送逻辑写成了同步阻塞调用且未设置超时。一个邮件发送慢拖垮了整个下单链路。教训是所有外部依赖必须异步化或设置严格超时并有熔断降级预案。现在我们的规范是任何HTTP调用connectTimeout和readTimeout必须显式设置且不超过1s。4. 场景化深度解析不同系统下的指标权重与陷阱4.1 高并发读场景如新闻APP首页QPS是王TPS是影子这类系统的特点是用户请求高度同质化都是刷首页Feed流数据更新频次低新闻内容几分钟一刷业务逻辑极简基本就是查缓存查DB。此时QPS是核心命脉TPS几乎可以忽略。为什么QPS最重要因为用户的“刷”这个动作就是最原始的QPS。每秒有10万人刷新首页系统就必须能扛住10万QPS。这里的“成功”就是返回一个200状态码和JSON数据哪怕数据是5分钟前的用户也接受。典型陷阱过度优化TPS。有人会想“我要保证每秒10万次‘首页加载成功’的TPS”。这完全是伪需求。首页加载没有“事务”概念它就是一个纯读操作。强行给它套TPS只会增加不必要的埋点和监控复杂度。优化重点极致的缓存策略多级缓存CDN - Redis - 本地Caffeine、读写分离、数据库分库分表应对海量用户ID查询、静态化将首页渲染成HTML片段。我们曾通过将热门新闻Feed流预生成并缓存在CDN将QPS承载能力从5万提升到50万成本几乎为零。4.2 强一致性写场景如银行转账TPS是圣杯QPS是仆人这类系统的核心是“资金安全”每一笔转账都必须满足ACID不容半点差错。此时TPS是唯一有意义的指标QPS只是TPS的“输入流量”。为什么TPS是圣杯因为老板只关心“每秒能完成多少笔真实的、原子性的转账”。QPS1000但如果其中300笔因余额不足失败TPS700这个700才是业务产能。而且TPS必须附带严格的SLAP999响应时间2s错误率0。典型陷阱用QPS来考核写系统。某次运维团队为了提升QPS将数据库连接池从100调到500。结果在大促时大量连接争抢锁TPS不升反降还引发了连锁超时。问题根源是写操作的瓶颈从来不在连接数而在锁竞争和磁盘IO。优化重点数据库选型如TiDB、OceanBase等NewSQL、精细化锁控制行锁代替表锁、异步化非核心流程如记账成功后异步发短信、极限压测用真实交易流水回放。我们曾对核心账务库进行“全链路压测”发现当TPS超过1200时MySQL的innodb_row_lock_time_avg飙升果断引入分库分表将单库TPS压力控制在800以内保障了大促零资损。4.3 混合型业务系统如电商平台三者共生动态权重这是最复杂的场景一个系统里既有高QPS的读商品详情页又有高TPS的写下单还有长耗时的批处理日终对账。此时不能一刀切必须按业务域划分指标权重。商品中心读为主QPS是核心KPI目标是支撑大促期间千万级UV的详情页访问。TPS在这里指“商品信息更新成功”的次数但更新频次很低一天几次所以权重低。订单中心写为主TPS是核心KPI目标是每秒稳定创建1000笔订单。QPS在这里指“创建订单”接口的调用量但它必须和TPS强绑定QPS≈TPS因为失败率要0.1%。营销中心混合QPS用户领券和TPS优惠券核销成功都要盯。但两者关系是非线性的一个用户可能领10张券QPS高但只在下单时核销1次TPS低。所以要分别设定阈值并监控两者的转化率核销数/领取数。实操心得我们为不同业务域建立了“指标矩阵”。例如订单中心的SLA是TPS≥1000P95≤300ms错误率≤0.05%商品中心的SLA是QPS≥50000P95≤100ms缓存命中率≥95%。这个矩阵写进每个服务的SLO文档是发布上线的强制准入门槛。没有这个矩阵所有性能优化都是盲人摸象。5. 常见问题与避坑指南那些年踩过的“指标”深坑5.1 “QPS上去了但用户说更卡了”——响应时间与QPS的悖论这是一个高频问题。现象是经过优化QPS从5000提升到8000但用户反馈页面加载变慢监控显示P95从200ms涨到800ms。根本原因QPS提升是通过“降低单请求成本”实现的但新方案引入了更高延迟的操作。例如为了提升QPS将原来一次数据库查询改为先查RedisRedis没命中再查DB。这看似合理但如果Redis集群网络抖动大量请求会fallback到DB导致DB压力剧增P95飙升。此时QPS是上去了因为Redis响应快但整体用户体验恶化了。破解之道永远用“P95响应时间”作为QPS提升的否决票。任何优化方案必须保证在目标QPS下P95不劣于基线。我们现在的压测流程是先固定P95目标如≤300ms然后逐步提升并发看QPS能到多少。而不是反过来。5.2 “TPS达标了但数据库CPU爆了”——资源消耗与指标的失衡现象压测报告显示TPS1000完美达标。但运维报警数据库CPU持续95%以上随时可能宕机。根本原因TPS只衡量了“成功数量”没衡量“成功所付出的代价”。一个低效的SQL可能让TPS1000的同时CPU吃满而一个优化后的SQL可能让TPS1200CPU只用60%。后者才是可持续的健康TPS。破解之道将资源利用率CPU、内存、IO等待作为TPS的“伴生指标”。在容量规划时不仅要定TPS目标还要定“在TPSX时数据库CPU75%”。我们有一个“黄金比例”经验当TPS提升20%而数据库CPU增长超过10%就要警惕必须深入分析SQL执行计划。5.3 “吞吐量测试跑了1小时结果发现最后10分钟TPS断崖下跌”——稳定性测试的致命漏洞现象吞吐量测试报告写着“60分钟稳定处理60万订单”但仔细看曲线前50分钟TPS1000最后10分钟TPS200平均下来是1000。这显然不合格。根本原因测试设计缺陷。没有设置“稳态期”和“衰减期”的明确区分。真正的吞吐量测试必须包含预热期5-10分钟让JVM JIT编译、缓存预热、连接池填满。稳态期至少30分钟以目标TPS恒定施压所有指标TPS、P95、错误率、资源必须全程稳定。衰减期5-10分钟逐步降低压力观察系统能否平滑恢复。如果稳态期内任何指标波动超过5%即视为测试失败。破解之道用自动化脚本驱动压测。我们用Jenkins Pipeline集成JMeter和Prometheus自动执行“预热-稳态-衰减”三阶段并在稳态期每分钟校验一次指标一旦超标立即终止并告警。这比人工盯屏可靠一万倍。5.4 “线上QPS是5000压测怎么也跑不到”——环境差异的隐形杀手现象线上监控显示QPS峰值5000但在同等配置的压测环境JMeter最大只能跑到3000。根本原因线上环境有大量“免费”资源而压测环境是“裸机”。主要差异点缓存热度线上Redis/Memcached已有海量热数据压测环境是冷启动大量请求穿透到DB。JVM状态线上JVM已运行数天JIT编译充分GC稳定压测环境是新启进程初期GC频繁。网络拓扑线上请求来自全球用户网络延迟天然存在反而降低了瞬时并发冲击压测是本地发起毫秒级延迟容易形成“请求风暴”。破解之道压测必须“仿真”。缓存预热压测前用历史流量回放将热点数据提前灌入Redis。JVM预热压测脚本启动后先以低并发运行10分钟再进入正式压测。网络延迟注入在JMeter中为每个请求添加随机的Constant Timer如100-500ms模拟真实网络抖动。我们曾通过这三步将压测QPS从3000提升到5200与线上峰值高度吻合。6. 终极心法把指标变成团队的语言和肌肉记忆聊了这么多技术细节最后想分享一点更底层的东西指标的价值不在于数字本身而在于它能否成为团队沟通的共同语言能否沉淀为工程师的本能反应。在我带过的几个团队里最成功的做法是把TPS/QPS/吞吐量的要求像呼吸一样融入到日常开发的每一个环节需求评审阶段产品经理提需求时必须附带“预期TPS”和“P95目标”。例如“双11期间首页‘猜你喜欢’模块预期QPS峰值5万P95≤150ms”。没有这个技术侧有权拒接需求。技术方案设计阶段架构师出方案时必须包含“容量估算”。例如“预计QPS5000按单请求DB耗时5ms需DB QPS5000换算为TPS5000考虑20%冗余目标TPS6000对应数据库连接池需配置为...”。Code Review阶段除了看功能逻辑必须检查埋点代码。Reviewer会问“这个order_created_success事件是在事务提交后发出的吗如果发消息失败会不会影响事务”上线发布阶段发布Checklist第一条“确认新版本在预发环境TPS/P95/错误率均符合SLO”。不符合立刻回滚。久而久之当一个新人听到“TPS掉了一半”他第一反应不是去查日志而是打开Grafana看QPS是否同步掉再看链路追踪找耗时最长的Span。这种条件反射比任何文档都管用。我个人在实际操作中的体会是别把TPS、QPS、吞吐量当成三个孤立的数字去记。把它们想象成一辆车的仪表盘——QPS是油门踏板的深度你踩得多猛TPS是车轮实际转过的圈数你真正走了多远吞吐量则是这趟旅程的总里程你最终抵达了哪里。油门踩得再猛车轮不转里程不会增加车轮转得再欢方向错了里程也是白费。唯有三者协同方向盘业务目标握稳这辆车才能又快又稳地驶向目的地。
返回列表