同一份工作量,四种走法
这是这本书的招牌。五行数据,利用率、吞吐、平均服务时间三项完全相同——按任何一个常规监控指标看,它们是同一个系统。而平均等待从 0 走到 22 个服务时长。
五个系统,每一个都满足下面全部三条:
- 平均每 1.25 个时间单位来一个请求(吞吐相同);
- 平均每个请求花 1.00 个时间单位(速度相同);
- 因此利用率都是 80%(忙闲相同)。
它们唯一的区别是「整齐程度」:一个全定时,一个只有到达随机,一个只有服务随机,一个都随机,一个服务时间忽快忽慢。
最慢的那个和最快的那个,平均等待差多少倍?
五行
| 走法 | ca² | cs² | 精确等待 | p99 | 天花板 |
|---|---|---|---|---|---|
| D/D/1 都定时 | 0 | 0 | 0.0000 | 0.00 | 100.0% |
| D/M/1 定时来、随机走 | 0 | 1 | 1.6927 | 10.74 | 80.0% |
| M/D/1 随机来、定时走 | 1 | 0 | 2.0000 | 10.56 | 80.0% |
| M/M/1 都随机 | 1 | 1 | 4.0000 | 21.11 | 66.7% |
| M/H₂/1 忽快忽慢 | 1 | 10 | 22.0000 | 140.48 | 26.7% |
五行的前三项指标——利用率、吞吐、平均服务时间——完全相同。如果你只有一套标准监控,这五个系统在你的面板上长得一模一样。
而用户体验到的是最后三列。
逐行读
第一行:0。不是「很小」,是零
D/D/1:每 1.25 个时间单位准时来一个,每次服务准时花 1.00。
第一位来了,服务到 1.00,走。第二位在 1.25 来,服务台空着,立刻开始。第三位在 2.50 来,上一位 2.25 就走了。永远不会有第二个人在场。
这台机器忙到 80%,队列长度恒等于 0 或 1。第 11 章在真机上验证过:800 个请求,平均等待 0.0006 毫秒,而那 0.6 微秒是时钟噪声。
这一行的意义是:「高利用率必然导致排队」是错的。利用率本身不产生队。产生队的是利用率和不齐的乘积。
第二、三行:不齐从哪来,账单差不多
D/M/1(1.6927)和 M/D/1(2.0000)很接近。一个是「来得准但做得不准」,一个是「来得不准但做得准」。
Kingman 公式对这两行给出同一个答案(都是 2.0000),因为它只看 (ca²+cs²)/2,两行都是 0.5。精确解说明它们其实略有不同——服务的不齐比到达的不齐贵一点点——但同一个量级。
这印证了第 8 章那句话:到达的不齐和服务的不齐地位平等。这在实践上很重要,因为大多数人只想着治理服务(优化慢查询),从没想过治理到达(给定时任务加抖动、给上游做速率整形)。
第四行:4.0000,教科书默认款
M/M/1。到达是泊松、服务是指数。这是所有排队论教材的第一个例子,也是绝大多数「按经验估一下」时脑子里默认的模型。
而第 5 章说过,真实的软件服务,cs² 几乎总是大于 1。所以这一行不是「悲观估计」,它是乐观估计。
第五行:22.0000,也就是你的系统
M/H₂/1,cs²=10。这对应什么?大概是:
- 大部分请求命中缓存,少部分回源;
- 大部分查询走索引,少部分全表扫;
- 大部分用户数据量小,少部分是重度用户。
换句话说,这一行才是绝大多数真实服务的形状。而它的平均等待是 M/M/1 的 5.5 倍,是那个「教科书默认款」的五倍半。
它的 p99 是 140.48 个服务时长。如果一次服务是 10 毫秒,那就是 1.4 秒——在一台忙到 80%、平均处理时间 10 毫秒的机器上。
「天花板」那一列回答的是:如果我的要求是「平均等待不超过 2 个服务时长」,我能把机器用到多满?
ρ★ = SLA ÷ (SLA + k × E[S]) k = (ca² + cs²)/2 全定时 k=0 → ρ★ = 100.0% 机器可以榨干 D/M 或 M/D k=0.5 → ρ★ = 80.0% 都随机 k=1 → ρ★ = 66.7% 忽快忽慢 k=5.5 → ρ★ = 26.7% ★ 七成多的产能必须空着
最后一行的意思是:如果你的服务 cs² 是 10,那么你买十台机器,只有不到三台在为吞吐服务,剩下七台是在为「不齐」买单。
反过来说:把 cs² 从 10 压到 1,你的机器数可以减到 40%——什么代码都不用重写,只要让慢请求别那么慢。这是这本书里性价比最高的一句话。
这些数字是怎么来的
「精确」那一列不是模拟出来的,也不是查表来的,是五个不同的闭式解各自算的:
| 行 | 怎么算的 |
|---|---|
| D/D/1 | 精确的 0。定时来定时走,ρ<1 时永远不排队 |
| M/D/1 | Pollaczek–Khinchine:ρ/(1−ρ) × (1+0)/2 × E[S] |
| M/M/1 | ρ/(1−ρ) × E[S] |
| M/H₂/1 | Pollaczek–Khinchine:ρ/(1−ρ) × (1+10)/2 × E[S] |
| D/M/1 | 没有初等闭式解,要数值解 σ = e^(−(μ/λ)(1−σ)),ρ=0.8 时 σ = 0.628630,然后 Wq = σ/(μ(1−σ)) |
而 demo 里的「模拟」那一列,是引擎真的一个一个顾客排出来的(每行四十万位顾客,用第 11 章验证过的那行 Lindley 递推)。两条路互相对照——这是这本书唯一能做的「与标准实现对比」,因为排队论没有标准实现。
另外四行都能一步写出来,唯独 D/M/1 要解一个超越方程。这个不对称本身很有意思。
原因是 Pollaczek–Khinchine 公式(那个能一步算的)要求到达是泊松的。泊松有一条特殊性质(PASTA,第 7 章提过):到达者看到的系统状态,等于时间平均的系统状态。这条性质让推导可以「站在到达者的角度」直接写下来。
定时到达没有这条性质。定时到达的顾客看到的世界,和随便挑一个时刻看到的世界不一样——他们总是在固定的相位上到达。于是就得老老实实解一个不动点方程:
σ = e^(−(μ/λ)(1−σ)) ← σ 是「来的时候得等」的概率 # ρ=0.8 时用二分法解出 σ = 0.628630 # 也就是说,定时到达的顾客里,62.86% 的人要等; # 而 M/M/1 里这个数是 ρ = 80%。 # 定时到达让「要等的人」少了 17 个百分点 —— 这就是那 1.6927 vs 4.0000 的来源。
顺便,这也是第 8 章那张「Kingman 在哪里不准」的表的来源:Kingman 对 D/M/1 在低利用率下偏 96.1%,正是因为它用了一个「假装到达是泊松」的近似。
「两个系统负载相同」这句话,在这一章之后应该拆成三句:
- 吞吐相同(λ 一样);
- 利用率相同(ρ 一样);
- 不齐程度相同(ca²、cs² 一样)。
前两条是大家都会说的,第三条几乎没人说——而这一章证明了,只有第三条不同,就足以让两个系统的用户体验差 22 倍。
所以下次做容量规划、做压测、做 A/B 对比时,如果只对齐了前两条,那你比较的其实是两个不同的系统。
为什么两个「一模一样」的服务表现不同。同样的代码、同样的机器、同样的 QPS,A 机房比 B 机房慢一倍。查了一圈没发现差异——因为差异在 c² 上:B 机房的流量里混进了一个批量作业,或者某个大客户的请求集中打在了那边。去比一比两边的延迟直方图形状,而不是平均值。
为什么隔离「大客户」那么有效。把大客户的请求路由到独立的池子,这个动作在吞吐上什么也没做——总工作量一点没变。但它把一条 cs²=10 的队,拆成了两条 cs² 都接近 1 的队。按这张表,那是从第五行回到第四行,等待降到 18%。这大概是分级隔离最被低估的收益。
为什么固定大小的批次比动态批次好。动态批次(有多少凑多少)让服务时长变得参差,cs² 上升。固定大小的批次牺牲一点灵活性,把 cs² 压到接近 0。第 20 章会算这笔账。
被刻意构造的其实是第四行。M/M/1(指数服务时间)是教科书为了数学方便挑的,它在真实软件里几乎不存在——软件的服务时间要么很整齐(固定计算量),要么很不齐(有缓存、有分支、有 IO),很少恰好落在「无记忆」这个特殊点上。
所以这张表的正确读法不是「从 0 到 22 是一个夸张的范围」,而是:你的系统大概在第五行,而你有办法把它挪到第二三行。那是四倍到十倍的改善,不需要加一台机器。
D差无穷倍——最快的那个精确等于 0。
如果不算第一行(有人会觉得那是耍赖),那么第二行到第五行差 13.0 倍(1.6927 → 22.0000)。选 C 的人也基本对了。
但第一行不是耍赖,它是这一章最重要的一行。它证明的是一个结构性的事实:排队的成因里,「不齐」不是一个修正项,它是一个可以把答案变成零的主因。ρ=0.8 这个数字,在 c²=0 时对等待没有任何贡献。
A 「三项指标都一样,能差到哪去」——这正是这一章要打的靶子。那三项指标恰好是标准监控面板上有的三项,而它们对这个问题几乎没有信息量。 B 「5 到 10 倍」——这是第四行到第五行的差距(4.0000 → 22.0000 是 5.5 倍)。如果你的直觉停在「随机 vs 很不齐」这个对比上,这个答案是对的。 C 「几十倍」——如果排除掉第一行,这个答案基本正确(13 倍)。而看 p99 那一列的话,从 10.56 到 140.48 也是 13 倍多。这一章的一句话
同样忙、同样快、同样的吞吐,等待可以从 0 到 22——而这个区间在你的监控面板上是不可见的。
卷 III 结束。你已经完整地看过那面墙了。下一卷问一个很自然的问题:那加机器呢?答案会比你想的复杂三层。第 13 章先从一个所有人每天都在做的选择开始:同样是 4 个窗口、同样的人流,排一条队还是各排各的?答案是 4.57 倍的差距——而且叫号机卖给你的,其实不是公平。