数据库、缓存、MQ 与 GC 性能链:端到端时间究竟花在哪里
局部优化会迁移瓶颈,关键路径必须用同一时间轴闭合。
HotSpot G1 调优 要求基于实际阶段日志判断暂停与吞吐取舍。
故障现场:局部数字为什么会给出错误结论
缓存命中路径提速后入口吞吐翻倍,数据库回源和消息生产超过容量;接口 p50 下降,数据库锁等待、MQ 积压和 GC 分配率却持续上升。 第一条规则是同时保存负载输入、业务输出和资源水位;只有结果数字而没有发生条件,无法区分代码变化、环境噪声、缓存热度和依赖波动。
先固定权威测量对象
用 trace/operationId 关联缓存决策、SQL 等待与执行、消息确认、分配率和 GC 暂停;数据库提交和消费水位才证明业务完成。 正向实验达到预期吞吐和延迟,反向实验制造饱和、队列、暂停或依赖退化,并证明指标能揭示而非掩盖差异。
六段性能主链
Request
在 Request 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
Cache / fallback
在 Cache / fallback 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
SQL / lock
在 SQL / lock 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
Message backlog
在 Message backlog 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
Allocation / GC
在 Allocation / GC 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
User outcome
在 User outcome 阶段记录时间戳、计数、资源 owner、上限和失败原因。测量探针的开销单独评估;并行阶段按关键路径组合,串行阶段才允许求和。改变参数后重新验证上下游水位,避免把等待从一个队列搬到另一个队列。
性能结论先声明系统边界与负载模型
性能不是代码固有属性,而是代码、数据、机器、运行时、依赖和请求到达过程共同产生的结果。同一接口在低并发下只有服务时间,在接近饱和后主要消耗于排队;同一 SQL 在热缓存、冷缓存、不同选择性和锁竞争下不是同一个实验。结论必须写清入口和终点、成功定义、数据规模、读写比、到达率、并发、突发、持续时间、机器与容器限额。
分布、排队和守恒关系必须同时成立
负载发生器也会制造测量错误
预热用于类加载、JIT、连接、缓存和数据页稳定,不应把预热最慢样本悄悄删除后声称冷启动也达标。稳态通过吞吐、分配率、GC、CPU 和队列趋势判断;持续增长的堆、积压或连接等待说明系统未稳态。测试结束需要降载和排空阶段,确认未完成任务、消息和异步写入最终收敛。
资源池必须沿同一截止时间协作
虚拟线程降低线程持有成本,不增加数据库连接、CPU 或远端 QPS;连接池扩大会增加数据库活跃会话和锁竞争;批量与压缩减少网络调用却增加内存、延迟和 codec CPU。任何参数变化都观察瓶颈是否迁移,不能只看被优化局部的耗时。
JVM、GC 与操作系统证据不能脱离业务负载
分配率、存活集、晋升、GC CPU、暂停和 safepoint 与业务延迟在同一时间轴分析。一次长暂停可能直接进入 p99,也可能让队列在暂停后形成更长恢复尾巴。堆加大可能降低回收频率却增加内存占用和故障恢复时间;更换收集器是吞吐、延迟、CPU 与 footprint 的取舍,不是无条件升级。
CPU 利用率低不代表有余量,线程可能等锁、连接、磁盘或网络;CPU 高也可能是序列化、压缩、GC、TLS 或自旋而非业务计算。结合运行队列、上下文切换、缺页、磁盘时延、网络重传和容器 throttling,先定位资源需求再调整参数。
性能数据同样需要安全与治理
压测数据使用合成或脱敏内容,压测身份限制权限和额度,发生器不能误指向生产。响应样本、SQL、Trace 和堆制品可能包含敏感字段,按最小采集、加密、访问控制和保留期治理。对外接口的容量数字不公开到能帮助攻击者精确选择放大点,内部又必须让 owner 能复现实验。
用阶梯负载画出拐点而不是只压一个峰值
分层剖析必须回答时间和资源去了哪里
先用低开销信号定位区间:端到端直方图、线程/连接队列、数据库等待事件、消息最老年龄、GC 与 CPU。只有证据指向 CPU 热点时才使用采样剖析;指向锁或 IO 时分析阻塞栈、锁 owner、系统调用和下游。一次剖析同时保存采样时长、频率和开销,避免探针改变调度或分配后把测量结果当原貌。
基准结果需要反事实与可回滚证据
两个 Java 17 模型固定量化见证
离线模型不冒充真实压测,只固定公式、边界和判定输出;真实环境再用直方图、JFR/GC 日志、数据库与消息指标证明同一不变量。
javac --release 17 -Xlint:all -Werror examples/backend-development/performance/database-cache-mq-gc/CriticalPathDemo.java examples/backend-development/performance/database-cache-mq-gc/BottleneckMigrationDemo.java
java -cp examples/backend-development/performance/database-cache-mq-gc CriticalPathDemo
java -cp examples/backend-development/performance/database-cache-mq-gc BottleneckMigrationDemototalMs=240 cacheMs=2 sqlWaitMs=120 sqlExecMs=35 mqAckMs=48 gcPauseMs=35 sumVerified=true
beforeRps=400 afterCacheRps=900 dbCapacityRps=650 backlogPerSec=250 bottleneckMoved=CACHE_TO_DB容量、回归与恢复门禁
对每层记录服务需求、最大吞吐、饱和水位和失败策略,优化后重新寻找约束资源;总时间按关键路径而非所有并行子任务简单求和。 围绕“端到端性能结论由同一请求时间轴、权威状态和资源水位共同证明,局部提速不能掩盖瓶颈迁移”保存基线、候选、差值、原始分布和权威结果。过载实验还要证明拒绝有界、关键流量受保护、积压排空且恢复迟滞不会制造二次冲击;不满足任一项即阻止发布或自动回滚。
