ρ 除以「1 减 ρ」
这是一个中学就见过的函数,图像你也画过。但几乎没有人在工作里认出它——因为在工作里,它藏在「利用率」这个听起来像效率指标的词后面。这一章把它画出来,然后一整卷都不换图。
你的服务现在跑在 50% 的利用率上,平均等待 1 个服务时长。
业务增长,流量翻倍多一点,利用率涨到 90%。机器没换,代码没改,请求的分布也没变。
平均等待会变成几倍?
再顺手估一个:从 90% 再涨到 95%(只多 5 个百分点),又是几倍?
那条曲线
第 8 章那个公式的第一个因子:
f(ρ) = ρ ÷ (1 − ρ)
把它填几个数:
| 利用率 ρ | 余量 1−ρ | ρ/(1−ρ) | 相对 50% 时 |
|---|---|---|---|
| 50% | 50% | 1.00 | 基准 |
| 70% | 30% | 2.33 | 2.3 倍 |
| 80% | 20% | 4.00 | 4 倍 |
| 90% | 10% | 9.00 | 9 倍 |
| 95% | 5% | 19.00 | 19 倍 |
| 99% | 1% | 99.00 | 99 倍 |
看第二列和第三列。它们的乘积永远接近 1。这不是巧合:
ρ/(1−ρ) ≈ 1/(1−ρ) 当 ρ 接近 1 时 # 换句话说,那条曲线的高度 ≈ **余量的倒数** # 余量 50% → 高度 1 # 余量 10% → 高度 10 # 余量 1% → 高度 100 # 余量 0 → 高度 ∞ ← 那面墙
这是这本书最该记住的一句话:等待时间反比于余量。不是反比于「机器数量」,不是反比于「速度」,是反比于你留下的那点空。
母题的三个部件
上面那张图会在这本书剩下的每一章重新出现。它有三个部件,各自都有意义:
那条上翘的曲线
它在 ρ=0 附近几乎是平的——这就是为什么低负载时你完全感觉不到排队的存在,也就形成了「产能够就没事」的直觉。然后它在某个地方开始起飞,而起飞的位置比大多数人以为的早得多。
那条水平线:「我最多能忍多久」
这是你唯一能自己定的东西。它可能是一个 SLA、一个超时值、或者仅仅是「用户开始抱怨的那个点」。
它必须被显式画出来,因为没有它,那条曲线是没法读的。「等待 4 个服务时长」是好是坏?不知道,取决于你能忍多久。
交点:ρ★,你真正的天花板
这是这本书里最实用的一个数。它回答的问题是:在我能接受的延迟下,我最多能把机器用到多满?
而它有闭式解,一行就能算:
# 让 Kingman 公式等于你能忍的上限,解出 ρ ρ/(1−ρ) × k × E[S] = SLA k = (ca² + cs²)/2 ρ★ = SLA ÷ (SLA + k × E[S]) ★ 这是全书最值钱的一行 # 举例:一次服务 1 个时间单位,我最多能忍等 2 个 k = 0.5(服务完全整齐) → ρ★ = 2 ÷ (2 + 0.5) = 80.0% k = 1 (都是纯随机) → ρ★ = 2 ÷ (2 + 1) = 66.7% k = 5.5(很不齐) → ρ★ = 2 ÷ (2 + 5.5) = 26.7% k = 15.5(非常不齐) → ρ★ = 2 ÷ (2 + 15.5)= 11.4%
读最后四行。同样的机器、同样的容忍度,「不齐」把你能买到的产能从 80% 砍到 11.4%。
不齐不会移动那面墙(墙永远在 ρ=100%)。它做的是把整条曲线乘高。
但因为你的容忍线是水平的,曲线抬高的结果就是交点往左搬——你的有效天花板提前了。
这就是为什么这本书叫《撞墙》而不是《满载》:你撞上的从来不是 100% 那道墙,而是你自己那条容忍线和曲线的交点。而那个交点在哪,一半由你的机器决定,一半由「你的请求有多不齐」决定。
那 30% 不是浪费
上面那张图里有一片青色区域,从 ρ★ 一直到 100%。它是这本书唯一的道德主张:
那片空着的产能不是浪费,它是你花钱买下来的响应时间。
这句话之所以需要被说出来,是因为几乎所有的组织激励都在往反方向推。「服务器利用率只有 40%,太浪费了」是一句在预算会上很难反驳的话——因为它把利用率当成了效率指标,而效率是不需要辩护的。
而正确的反驳是:把那 40% 用掉,你买到的是吞吐;付出的是一条起飞的延迟曲线。这是一笔交易,不是一次纠错。至于这笔交易划不划算,取决于你的容忍线画在哪——但它必须被当成一笔交易来讨论。
这也解释了一件让很多工程师困惑的事:为什么云厂商的「弹性」值那么多钱。弹性卖的不是机器,是「让你不必长期持有余量」。你只在需要的时候买那 30%,其余时间不付钱。它把「余量」从一项固定资产变成了按需消费。
那个 1 − ρ 不是拟合出来的,它有一个非常直白的来源:队列必须靠余量来排空。
# 一个忙期是怎么结束的? # 每单位时间,服务台干掉 μ 个活,同时又来了 λ 个新的。 # 净排空速度 = μ − λ # 所以清掉一个长度为 L 的队,需要 # 排空时间 = L ÷ (μ − λ) = L ÷ (μ(1 − ρ)) # ↑ 就是它 # 余量减半 → 排空速度减半 → 队列存在的时间翻倍 → 平均队长翻倍 # 余量 → 0 → 排空速度 → 0 → 队永远排不空
所以「墙」在物理上的含义是:当 ρ = 1 时,队列没有任何机制可以缩短。它不是「变得很长」,它是「不再有回落的力量」。任何一次波动造成的积压,都会永久地留在系统里——第 21 章会把这件事算成一笔具体的债。
「余量」在工程语境里通常被理解成一种保险:万一流量涨了,还有富余。这个理解太弱了。
余量的真正作用不是应付「万一」,而是吸收每时每刻都在发生的不齐。即使你的流量一整年一个数都不涨,余量仍然每秒钟都在被用掉——用来吸收第 6 章那种成团到达、第 5 章那种参差服务。
余量不是备用的,它是消耗品。这也是为什么「平时用不到就是浪费」这个说法完全错了:它每一秒都在被用到,只是你看不见。
Kubernetes 的 HPA 目标值。默认的 CPU 目标常见设在 70%–80%。为什么不是 95%?就是这条曲线。而更有意思的是:正确的目标值取决于你的 c²——一个请求耗时很整齐的服务可以安全地跑到 85%,一个混着大小请求的服务可能 60% 就该扩容了。用同一个默认值管所有服务,是在赌它们的不齐程度差不多。
为什么医院不能满床。医疗管理研究里有一个被反复验证的经验值:占床率超过 85%,急诊等待时间和院内感染率会同时开始陡增。85% 这个数就是这条曲线和「病人可接受等待」的交点。而在预算压力下,很多公立医院被要求跑到 95% 以上——那正好在曲线起飞的位置。
你的日程表。把工作日排到 100% 的人,任何一个会议超时都会推倒后面全部安排。留 20% 空白的人不是效率低,他是在买响应能力。而且这两个人的「产出」在长期看未必有差别,因为前者的时间大量花在了重新安排上。
ρ/(1−ρ) 从 9.00 变成 19.00,是 2.1 倍。
这个错误直觉的根源,是把「利用率」当成了一个加法量来看待。90% 和 95% 看起来只差 5,但决定等待的不是这两个数本身,是它们的余量:10% 和 5%,差了一倍。
一个矫正直觉的办法:不要说利用率,改说余量。把「从 90% 涨到 95%」翻译成「余量从 10% 掉到 5%」,你的直觉会立刻正确起来——因为「减半」这个词你的直觉是懂的。
这个翻译习惯值得养成。这本书从这一章开始,会尽量在提到利用率时同时给出余量。
C9 倍。(0.9/0.1) ÷ (0.5/0.5) = 9.00 ÷ 1.00 = 9.0。
第二问:从 90% 到 95%,是 2.1 倍(19.00 ÷ 9.00)。再往上,从 95% 到 99% 是 5.2 倍。
把三个数连起来看,这一章的意思就全在里面了:利用率每往上走一步,代价都比上一步大。而这条曲线的形状,是你所有容量决策的底层地形。
A 「利用率涨 1.8 倍,等待涨 1.8 倍」——线性直觉。它在 ρ 很小的时候近似成立(曲线那段确实接近直线),这也是为什么这个直觉能存活这么久:在低负载下它是对的。 B 「大约 3 倍」——低估。有意思的是,3 倍对应的是从 50% 涨到 75% 左右。很多人对「变慢」的容忍度也大致停在 3 倍,这解释了为什么系统总是在 75% 附近开始被抱怨。 D 「超过 20 倍」——高估了。20 倍对应 ρ≈95%。不过如果同时考虑到高负载下 c² 往往也会变大(重试增多、超时增多),实际体验到的退化确实可能超过 9 倍。这个选项在实践中比它在数学上更接近真相。这一章的一句话
等待时间反比于余量;你撞上的不是 100% 那道墙,是你的容忍线和曲线的交点。
下一章把这条曲线换个方向读:既然等待反比于余量,那么买产能的价格也随位置变化。你会看到一条漂亮得不像话的恒等式——要把等待减半,需要增加的产能恰好等于你现在的余量。在 90% 的地方,加 10% 的机器等待减半;在 99% 的地方,只要 1%。而同一句话反过来读就是噩梦。