【背景】 我负责一个支付链路的前置服务(Java 17 + JDK 内置 HttpServer 前置 + HikariCP + Redis),稳态 1200 QPS,大促 4000 QPS。去年 SLO 把「核心接口 P99 < 120ms」写进 SLA,达标后 PM 追问了一句:「那 P99.9 呢?万一 0.1% 的用户遇到 800ms,客诉你怎么算?」于是我们拉了 30 天数据:P99=118ms,P99.9=842ms,P99.99=2.3s。团队里立刻分成两派,吵了两周没结论。我复盘时习惯从现象倒推根因:把 P99.9 的毛刺按 trace 拆开,60% 是 Full GC(G1 的 humongous allocation 触发 concurrent mark 暂停)、25% 是 Redis 大 key 的 GET 慢、10% 是下游偶发重试放大、剩下 5% 是真的网络抖动。——换句话说,P99 达标 ≠ 系统健康,但 P99.9 也不等于「用户真实体感」。
【常见分歧】
- 派 A(追 P99.9):P99.9 才是「真实用户里最痛的那批人」,客诉、资损、舆情都来自这 0.1%;P99 达标只是平均主义的胜利。
- 派 B(P99 够用):P99.9 受采样误差、时钟漂移、GC 单次毛刺影响极大,把它写进 SLO 等于把「偶发事件」当「持续状态」考核;优化 ROI 极低,3 天换来 0.1% 用户少等 100ms。
- 派 C(看场景):读多写少 / 幂等接口可以只盯 P99;资金、扣款、对账类必须盯 P99.9 甚至 P99.99;中间地带看业务 SLA 怎么签。
【我的倾向与理由】 我偏向派 C,但加一条硬约束:P99.9 只作为「诊断指标」,不作为「SLA 指标」。理由有三:
- 数据可信度:1200 QPS 下 P99.9 每小时只有 ~7 个样本,P99.99 每小时不到 1 个,统计意义弱到可以忽略;把它当 KPI 等于在噪声上做工程。
- 根因可定位性:P99.9 的毛刺 80% 来自 GC / 大 key / 重试放大,这些在 P99 上已经能看到「影子」——与其追 P99.9 的数字,不如把 P99 的分布形态(方差、长尾斜率)当预警信号。
- ROI:把 3 天投到 P99.9,大概率是在做「把 humongous allocation 拆小」这种局部优化;同样的 3 天投到「把 P99 从 118ms 压到 100ms + 把 GC 暂停从 200ms 压到 50ms」,覆盖的用户面大一个量级。
但我承认派 A 在「资金类、幂等性弱、客诉敏感」的场景是对的——所以我不反对 P99.9 进看板,只反对它进 SLA。
【想听大家在什么场景下怎么选】
- 你们团队的 SLO 写的是 P99 还是 P99.9?背后是业务倒逼还是工程师洁癖?
- P99.9 的毛刺,你们怎么区分「真网络抖动」和「本地 GC / 大 key / 重试放大」?有没有可复现的探针组合(eBPF / JVM flags / trace 字段)?
- 当 P99 达标、P99.9 毛刺持续存在,你怎么向 PM 解释「这 0.1% 不值得花 3 天」?还是你已经说服自己「值得」?
- GC 暂停(Full GC / concurrent mark)在你们 P99.9 毛刺里的占比大概多少?你们用什么手段把 GC 从「长尾嫌疑」里摘出去?
欢迎贴数据、贴配置、贴翻车案例——空谈「看场景」的请附上你的场景。
0赞
0收藏
0楼层