11.02 分布与统计:平均值为何掩盖 IM 尾延迟
返回第十一卷 · 前置:11.01 测量口径 · 调度前置:03.04
11.02 分布与统计:平均值为何掩盖 IM 尾延迟
DeepTutor 初稿经技术与教学审阅后的静态课程。所有时延、样本量、分位数、直方图与分组数字均为纸上假设;本次没有运行 Go、IM 服务、监控、性能基准、统计程序或站点构建。
“平均很快”,为什么仍有人一直等?
11.01 已要求每个指标写清用户动作、确认点、分母、单位和时间窗。本章假设以后某个教学 IM 收集到了同口径的“从用户点击发送到 A 收到服务端受理回应”的时延。有人只报告“平均 32.6 ms”,但另一位用户等了 200 ms。两句话可以同时为真:平均值压缩了一整组数据,却没有告诉我们最慢那一部分怎样分布。
先从十个可以手算的样本学均值、中位数和分位数,再用直方图和跨分组例子解释聚合风险。u-a/u-b/c-a/m-a 都是虚构身份;当前课程只有本地 CLI 和静态未来服务合同,不存在这些真实请求或监控样本。所有图表必须标“假设”,不能用来评价 OpenIM 或本项目的线上性能。
| 第一遍 | 第二遍 | 练习成果 |
|---|---|---|
| 样本、排序、均值、中位数 | 分位数、直方图、聚合与缺失样本 | 一张带算法、窗口、样本量的时延报告 |
一、先保证十个数测的是同一件事
设这十次请求都满足 11.01 的同一用户动作:合格的发送尝试,起点是 A 点击提交,终点是 A 收到 accepted_in_memory 回应,单位统一为毫秒;请求体大小、会话类型和实验条件在本题先视作相同。按从小到大排序得到:
10, 11, 12, 13, 14, 15, 16, 17, 18, 200 ms其中前九项接近 10–18 ms,最后一项为 200 ms。样本量是 n=10,不是“服务一天有十万请求”。这十个数也只描述已获得受理回应的请求;若同时还有超时或错误而未被列入,不能由这里的分布推断所有尝试都很快。
不能把“HTTP 历史查询耗时”和“发送受理回应耗时”混进同一数组,再给它一个“IM 消息时延 P99”的名字。也不能把 B 设备收到的延迟与 A 受理回应混算;两者终点不同。先守住 11.01 的测量合同,后面的统计计算才有业务含义。
二、均值和中位数各保留了什么信息
算术平均值把所有值相加,再除以样本量。这组数的前九项 10+11+…+18=126 ms,加上最后的 200,合计 326 ms;平均值为 326/10=32.6 ms。
中位数先排序,取位置最中间的值。n=10 为偶数,中间是第 5 个 14 ms 与第 6 个 15 ms,中位数为 (14+15)/2=14.5 ms。若 n 为奇数,则直接取中间那个位置。中位数说明一半样本不大于这个位置附近的值,并不承诺任何特定用户的时延。
| 汇总 | 本题数值 | 它给出的视角 | 它没有告诉你 |
|---|---|---|---|
| 最小值 | 10 ms | 最快的一个样本 | 普通请求有多快 |
| 中位数 | 14.5 ms | 样本中央位置 | 那个 200 ms 用户的体验 |
| 均值 | 32.6 ms | 十次耗时的总量分摊 | 具体尾部比例和最慢值 |
| 最大值 | 200 ms | 本批最慢的一项 | 长期极端情况的稳定概率 |
200 ms 把均值从“前九个数附近”拉高了;中位数则仍留在 14.5 ms。不能因此说“中位数比均值更真实”或“均值没用”:如果估算总服务时间或资源消耗,求和与均值可能重要;如果关心典型体验,中位数有帮助;如果担心少数用户非常慢,还要看尾部。一个数回答不了所有问题。
同一均值可以有完全不同的波动
再单独构造两份各 5 个样本 的纸上窗口,不要与上面的十个数混算:窗口 A 为 [20,20,20,20,20] ms,窗口 B 为 [5,5,5,5,80] ms。两组总和都为 100 ms,均值同为 20 ms;A 的每次体验完全相同,B 则有一位用户等了 80 ms,中位数仅 5 ms。若只报告“两个窗口平均 20 ms”,就看不出波动与尾部已经改变。
方差可用“每个值与均值的差先平方,再求平均”量化分散。把这五项当作本题全部对象,A 的方差是 0;B 的四个 5 各比 20 少 15,末项 80 比 20 多 60,故方差为 (4×15²+60²)/5=(900+3600)/5=900 ms²,标准差是平方根 30 ms,重新回到时间单位。这里采用题设总体分母 5;若把这五个值当作从更大总体抽取的样本来估计方差,会涉及另一种分母约定。标准差仍不能告诉你是哪位用户遇到 80 ms,所以要连同样本量、中位数、尾分位或直方图一起看。
三、最近秩分位数:先写算法,再报 P90/P99
本章用最近秩(nearest rank)作初学者可手算的定义:把 n 个数从小到大排序,p 分位数取第 ceil(p×n) 个值,位置从 1 开始。这里 p 用 0 到 1 的比例,例如 P90 对应 p=0.90。不同统计库与监控系统可能用插值、近似或其他定义;跨系统比较前要把算法或直方图精度写明,不能只看标签都叫 P99。
n = 10
P90 位置 = ceil(0.90×10) = 9 → 第 9 个 = 18 ms
P95 位置 = ceil(0.95×10) = 10 → 第 10 个 = 200 ms
P99 位置 = ceil(0.99×10) = 10 → 第 10 个 = 200 ms这组数据中,第 9 个是 18 ms,说明至少本批 90% 样本不超过它;P99 则等于最大值 200 ms。十个样本的 P99 只是这十个值里的最大值,非常不稳定。下批若 200 ms 事件没被抽中,P99 会骤然下降;若出现一次更慢事件,又会跃升。它不能作为长期线上尾延迟的可信估计,更不能用来宣称“99% 用户都在 200 ms 内”而不写明样本量、窗口和是否漏掉超时。
分位数还必须绑定事件口径。A 收到内存受理回应的 P99,不等于 B 设备送达的 P99;WebSocket Ping/Pong 的 P99 也不是消息处理的 P99。11.08 若以后选 SLO,先固定业务确认点,再决定阈值和观察窗口。
四、直方图保留分布轮廓,也会丢精度
直方图把数值归入互不重叠的区间,保存每个区间有多少样本。本章先用普通非累计桶:
| 时延区间 | 本题样本数 | 说明 |
|---|---|---|
[0,20) ms | 9 | 10–18 都在这里 |
[20,100) ms | 0 | 本批没有中间时延 |
[100,+∞) ms | 1 | 200 在这里 |
| 合计 | 10 | 与原始样本量相同 |
这张表能让你一眼看出“一大堆快、一个很慢”,比单独的 32.6 ms 均值更像原始分布。但它不能让你仅凭最后一桶知道那个慢样本恰好是 200 ms:它也可能是 120、500 或 5000 ms。区间边界必须明确是包含左端还是右端;本表的 [0,20) 含 0、不含 20。
Prometheus 一类监控系统的传统直方图桶常用累计计数,例如 le=20 ms 为 9,le=100 ms 仍为 9,+Inf 为 10;它们不能再简单相加为总数。本题没有恰好落在 20/100 ms 边界的值,所以普通区间和累计“≤”在这两个阈值上恰巧同数。若要恢复非累计 (20,100] 的数量,应计算“≤100 减去 ≤20”,并先对齐区间边界。本组还可另记 count=10、sum=326 ms;它们使均值可由 sum/count 算出,但也不能重建十个原值。
用桶估计 P99 时,最后一桶 [100,+∞) 太宽,无法给出精确的 200 ms;桶越细,所需观测与存储成本也会增加。11.03 才讲真实指标类型与采集;本章只要求先理解保存原值、保存桶和保存单个分位数分别损失了什么信息。
五、不能把各组 P99 简单平均成总体 P99
分位数取的是排序位置,不是像总耗时那样可直接相加的量。再造一个与前面十个样本完全独立的纸上例子,仍使用本章最近秩算法:
| 分组 | 100 个样本怎样组成 | 本组 P99 |
|---|---|---|
| A | 99 个 10 ms,1 个 1000 ms | 第 99 个 = 10 ms |
| B | 99 个 100 ms,1 个 1000 ms | 第 99 个 = 100 ms |
若直接平均两个 P99,得到 (10+100)/2=55 ms。但真正把两组 200 个原始样本合并后,排序位置 1–99 是 10 ms,100–198 是 100 ms,199–200 是 1000 ms。总体 P99 的最近秩位置为 ceil(0.99×200)=198,所以总体 P99=100 ms,不是 55 ms。
分组 P99 的平均:55 ms ← 不是总体分位数
合并原始样本后的 P99:100 ms为什么?A 的“第 99 个”和 B 的“第 99 个”是两份各自排序的位置,合并后每个值的名次会变化。若只保存了每组一个 P99,通常无法精确重建总体 P99;需要原始样本、合适的可聚合桶或其他有明确误差模型的分布摘要。不能用“两个分组大小一样”作为直接平均分位数的理由。
均值的聚合方式不同。另起一个独立例子:A 有 10 个请求,每个 10 ms;B 有 90 个请求,每个 100 ms。两组均值的简单平均是 (10+100)/2=55 ms,但全部 100 个请求的真实均值是 (10×10+90×100)/100=9100/100=91 ms。均值可以用总耗时之和 ÷ 总样本数重建,要按样本数加权;分位数不能照搬这个方法。两个例子样本构造不同,不要把 91 ms 和上面的总体 P99 100 ms 当作同一数据集的两种指标。
六、只统计完成请求会把慢失败藏起来
假设前面十个有回应的时延样本之外,同一批合格请求还有 5 次到观察期限仍未得到回应。如果仪表盘只把十个完成值算 P99,就得到 200 ms;但 5/15 的用户连完整回应都没有。至少应同时报告:完成/确认比例 10/15≈66.7%、已完成者的时延分布、超时或结果未知的 5 次。不能把五次写成 0 ms,也不能直接给它们一个“真实完成时延恰为超时时间”的值。
这些未完成请求有的可能稍后才处理完,有的可能永远失败。对它们来说,观察窗口结束只给出“到这个时刻还没见确认”的有限信息。若只保留快的完成样本、把慢和超时样本丢出计算,图上的平均和 P99 可以变好,但用户体验可能更差。11.01 的合格尝试分母与观察期限要与时延图并排展示;11.02 先识别这类缺失/截尾现象,不在没有更多假设时做精确统计估计。
样本量、时间窗、请求来源也会改变形状。一天低峰的十次与高峰的一百次不能只比较 P99 数字;若大消息、群聊或较慢地区请求在两个样本中比例不同,差异不必然来自代码改动。未来若做前后版本对照,应记录版本、同样的业务确认点、会话类型、消息大小、活跃连接、群目标数、时间窗口和失败样本;否则只是两份不同负载的描述,不能声称优化引起时延变化。
七、在 IM 业务里把分布和根因分开
同一条 m-a 至少有“从点击到 A 收到内存受理回应”的分布,以及未来“从点击到 B 设备确认”的分布。它们终点不同,不能放到同一张直方图后只标“发送时延”。如果服务端处理 P99 很低而 B 设备确认 P99 很高,可能在后续队列、连接、网络或设备;如果客户端受理回应慢,可能在请求入站、应用锁、网络返回等。分位数指出在哪个结果上变慢,不自动指出哪一行代码导致变慢。
一份可供后续诊断的最小报告应包含:
| 字段 | 本题怎样填写 | 为什么需要 |
|---|---|---|
| 用户目标 | u-a 提交 m-a,等待服务受理回答 | 不与设备送达混淆 |
| 样本集合 | 合格请求,注明失败/超时数量 | 防止只挑完成者 |
| 起止点和单位 | 点击→收到回应,ms | 让均值/P99有意义 |
| 时间窗/负载 | 具体起止,消息大小、活跃比 | 便于对照 |
| 分布表示 | count/sum、桶或样本,注明 P99 算法 | 避免平均分位数 |
| 仍未知 | CPU 等待、网络/存储阶段占比 | 不把症状当根因 |
03.04 已讲 CPU 等待与 I/O 等待,04.01 已讲传输、传播与排队。若尾部变坏,可提出几个候选假设并在 11.03 的阶段日志/Trace 中找时间证据;不能仅因 P99 从 100 升到 200 ms 就断定“CPU 不够”,也不能因为平均没变就否认少数用户的慢请求。
八、完整纸上报告与分层练习
学习者先用十个原始值独立复算,再用两组各 100 个值验证聚合反例,最后给 11.01 的发送/历史查询指标卡附上“样本量、失败数、分布摘要和未覆盖范围”四项。真实监控只能在以后有独立运行环境和采集链时记录;本轮是静态教材,没有 Go、IM 服务、基准或监控数据。
分层练习:先回答,再核对反馈
1. 这十个数的确认点是什么?
从 A 点击发送到收到本教学服务的内存受理回应,不是 B 设备收到。
2. 前九个整数 10 到 18 之和是多少?
126 ms。
3. 加上 200 后总耗时是多少?
326 ms。
4. 十个样本的均值是多少?
326/10=32.6 ms。
5. 十个样本的中位数是多少?
第 5 和第 6 项为 14、15 ms,平均为 14.5 ms。
6. 本章最近秩 P90 取第几个?
ceil(0.90×10)=9,第 9 项为 18 ms。
7. 本章最近秩 P99 是多少?
ceil(0.99×10)=10,第 10 项为 200 ms。
8. 十个样本的 P99 能稳定代表长期尾延迟吗?
不能。它在本题等于最大值,对单个极值和抽样非常敏感。
9. `[0,20) ms` 非累计桶有几项?
9 项,即 10–18 ms。
10. 累计 `le=100 ms` 桶有几项?
9 项。200 ms 不在其中。
11. 三个累计桶 9、9、10 能相加得总数 28 吗?
不能。它们相互包含,总数为 +Inf 的 10。
12. 只看 `[100,+∞)` 桶能知道慢项恰好是 200 ms 吗?
不能。该桶只说明它至少 100 ms。
13. A 组 99 个 10 ms、1 个 1000 ms 的最近秩 P99?
第 99 项为 10 ms。
14. B 组 99 个 100 ms、1 个 1000 ms 的最近秩 P99?
第 99 项为 100 ms。
15. 两组 P99 平均 55 ms 等于合并后 P99 吗?
不等于。合并 200 项的第 198 项为 100 ms。
16. 另例 A10×10、B90×100 的总体均值?
按样本数加权为 (100+9000)/100=91 ms,不是 55 ms。
17. 十次完成、五次超时,已确认完成比例?
10/15≈66.7%;时延图也需注明五次未确认。
18. 超时的五次能按 0 ms 参与均值吗?
不能。没有观测到完成时延,不是零时延成功。
19. A 受理回应 P99 与 B 设备送达 P99 可混成一组吗?
不能,两个分布的终点和业务问题不同。
20. 部署后 P99 升高就一定是 CPU 竞争吗?
不能。网络、队列、锁、存储和样本组成变化都需排查。
21. 均值与 P99 相同即可忽略样本量吗?
不能。样本量、算法、时间窗和遗漏失败决定结论范围。
22. 本章数字能当作 OpenIM 实测性能吗?
不能。它们全是纸上样本,本轮没有运行或采集。
来源与下一步
- Google SRE:Monitoring Distributed Systems与Workbook:Implementing SLOs:用户结果、延迟与观测口径的来源。
- Prometheus:Histograms and summaries:累计桶、分位数估计与跨实例聚合的后续参考。
- 11.01 业务测量:本章所有时延样本的分母与确认点前置。
下一章11.03 日志、指标与 Trace再把这些样本落到采集设计;进入前请能说明“一次 P99=200 ms”使用的算法、样本量、窗口、失败样本处理和业务确认点。