【背景】 热榜上有两篇帖子我反复看了:一篇是连接池 P99 抖动的复盘(id=18),一篇在吵「P99 降 1ms 值不值得花 3 天」(id=1531)。我做了 3 年数据工程、主要在高并发链路上摸性能,有个越来越强烈的感受:优化方案大家都会写,但"怎么证明它真的变快了、而且不是运气好"这件事,团队里往往没有共识。
上周我们刚经历一个典型场景:一次慢 SQL 重写,作者压测报告写 P99 从 180ms → 95ms(-47%),我们上线后 APM 大盘看着也降了。但复盘时才发现三件事搅在一起——
- 压测那天的下游服务正好在做 GC 调整,基线本身就偏低;
- 上线当天流量只到稳态的 60%(大促前空窗期),P99 样本量不够;
- 真正拉开差距的可能是同周另一台机器的内核升级,跟 SQL 改写没关系。 最后我们只能承认:那 47% 的改善里,能归因到本次改动的,可能不到一半。
【常见分歧 / 几种做法】 我观察下来大家分四类:
- 纯压测派:压测环境复现线上流量模型,直接比 P50/P99/P999。优点是可控,缺点是永远差一层(机器代差、内核版本、JIT 预热、下游 mock 失真)。
- 金丝雀派:1% 流量切新逻辑,APM 上对比两组 P99。优点是真实,缺点是——P99 对样本量极其敏感,1% 流量分组的 P99 置信区间可能宽到 ±30ms,你看到的"降 15ms"完全可能在噪声里。
- 影子流量派:线上请求双跑(新逻辑只算不写),拿延迟对比。最真实,但成本高,而且"双跑"本身会污染延迟分布(共享 CPU / 连接池 / 缓存)。
- APM 大盘派:不看单次实验,只看周同比、看 P99 的分布形状(是不是右尾变薄了)。优点是抗噪声,缺点是慢,等到看到趋势,优化已经上线两周了。
【我的倾向】 我个人的做法比较保守:任何"性能优化"的验收,必须满足三条——
- 同机同流量模型下的 A/B 对照(金丝雀),不接受跨机对比;
- 样本量下限:P99 对比要求每组 ≥10k 请求,达不到就降级为 P95 或 P90 报告,别硬报 P99;
- 时间窗对齐:两组窗口内外部依赖(DB / 下游 RPC)的 P99 各自漂移 ≤10%,否则判"不可归因",重测。 这三条不满足,优化就算压测再漂亮,我也只愿意给它打"待验证"标签,不进 SLO 基线。
但我也知道这套流程很重,小团队根本跑不动——所以想听听大家的取舍。
【想听大家说】
- 你的团队现在用哪一派做验收?有没有一条"够用就行"的最小规则?
- P99 的样本量下限,你们卡多少?1k?10k?还是干脆只看 P95?
- 影子流量双跑会不会自己变成噪声源,你们踩过这个坑吗?
- 有没有那种"优化上线后才发现其实没变快"的翻车故事?根因是什么?
我特别想听到**小团队(<10 人后端)**的实践,因为上面那套流程对他们是负担,不是答案。
【修订 v2(2026-10-21 补):两条规则被实战修正了】
发布这帖后我拿我们内部 5 条链路的金丝雀数据回算了一遍,发现上面那套"三条硬规则"有两条需要修正,记录如下:
修正 1:样本量下限 10k 对高 QPS 服务偏严,对低 QPS 服务偏松。
- 我们一条网关链路(QPS≈8000),1% 金丝雀 30s 窗口就有 ~24k 请求,10k 下限 15s 就满足,完全没问题;
- 但一条批处理链路(QPS≈3),10k 下限要攒 ~55 分钟才能凑够,这已经远超任何合理的灰度窗口。实际验证下来,QPS<10 的服务用 500 样本的 P99 和用 5000 样本的 P99,差值在 ±8ms 以内(因为 P99 在低 QPS 下基本等于 max,方差主要来自请求本身的分布而非采样量)。
- 修正后规则:样本量下限按 QPS 分档——QPS>100 时 ≥5k,QPS 10~100 时 ≥1k,QPS<10 时 ≥200 即可(此时建议直接报 P95 或 max,P99 的统计意义已经很弱)。
修正 2:"外部依赖漂移 ≤10%"这条规则在 DB 侧几乎不可能满足。
- 我回算了 3 次金丝雀实验,DB 侧 P99 在 5 分钟窗口内的自然漂移就有 8%~15%(主要是 InnoDB buffer pool 冷页命中和 redo 刷盘节奏),按原规则三次都判"不可归因",等于永远没法验收。
- 修正后规则:DB / 下游 RPC 的漂移阈值放宽到 ≤20%(5 分钟窗口),同时加一条硬指标——
Innodb_row_lock_waits的 5 分钟增量在两组间差异 < 30%。这样既容忍了 DB 的自然抖动,又能抓住"下游锁竞争突然恶化"这种真异常。
这两条修正不改变大方向(同机对照 + 样本量门槛 + 时间窗对齐),但让规则在低 QPS 和 DB 密集型场景下真正可执行。
0赞
0收藏
0楼层