卷 III · 那面墙CH 09深度 9/24

ρ 除以「1 减 ρ」

这是一个中学就见过的函数,图像你也画过。但几乎没有人在工作里认出它——因为在工作里,它藏在「利用率」这个听起来像效率指标的词后面。这一章把它画出来,然后一整卷都不换图。

★ 全书母题双曲线你真正的天花板

▷ 先估一个数

你的服务现在跑在 50% 的利用率上,平均等待 1 个服务时长。

业务增长,流量翻倍多一点,利用率涨到 90%。机器没换,代码没改,请求的分布也没变。

平均等待会变成几倍?

A 大约 1.8 倍——利用率涨了 1.8 倍嘛 B 大约 3 倍 C 9 倍 D 超过 20 倍

再顺手估一个:从 90% 再涨到 95%(只多 5 个百分点),又是几倍?

那条曲线

第 8 章那个公式的第一个因子:

f(ρ) = ρ ÷ (1 − ρ)

把它填几个数:

利用率 ρ余量 1−ρρ/(1−ρ)相对 50% 时
50%50%1.00基准
70%30%2.332.3 倍
80%20%4.004 倍
90%10%9.009 倍
95%5%19.0019 倍
99%1%99.0099 倍

看第二列和第三列。它们的乘积永远接近 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−ρ

那个 1 − ρ 不是拟合出来的,它有一个非常直白的来源:队列必须靠余量来排空

# 一个忙期是怎么结束的?
# 每单位时间,服务台干掉 μ 个活,同时又来了 λ 个新的。
# 净排空速度 = μ − λ

# 所以清掉一个长度为 L 的队,需要
#   排空时间 = L ÷ (μ − λ) = L ÷ (μ(1 − ρ))
#                                    ↑ 就是它

# 余量减半 → 排空速度减半 → 队列存在的时间翻倍 → 平均队长翻倍
# 余量 → 0  → 排空速度 → 0 → 队永远排不空

所以「墙」在物理上的含义是:当 ρ = 1 时,队列没有任何机制可以缩短。它不是「变得很长」,它是「不再有回落的力量」。任何一次波动造成的积压,都会永久地留在系统里——第 21 章会把这件事算成一笔具体的债。

✎ 术语正名:「余量」(headroom / slack)

「余量」在工程语境里通常被理解成一种保险:万一流量涨了,还有富余。这个理解太弱了。

余量的真正作用不是应付「万一」,而是吸收每时每刻都在发生的不齐。即使你的流量一整年一个数都不涨,余量仍然每秒钟都在被用掉——用来吸收第 6 章那种成团到达、第 5 章那种参差服务。

余量不是备用的,它是消耗品。这也是为什么「平时用不到就是浪费」这个说法完全错了:它每一秒都在被用到,只是你看不见。

▸ 在现实里

Kubernetes 的 HPA 目标值。默认的 CPU 目标常见设在 70%–80%。为什么不是 95%?就是这条曲线。而更有意思的是:正确的目标值取决于你的 ——一个请求耗时很整齐的服务可以安全地跑到 85%,一个混着大小请求的服务可能 60% 就该扩容了。用同一个默认值管所有服务,是在赌它们的不齐程度差不多。

为什么医院不能满床。医疗管理研究里有一个被反复验证的经验值:占床率超过 85%,急诊等待时间和院内感染率会同时开始陡增。85% 这个数就是这条曲线和「病人可接受等待」的交点。而在预算压力下,很多公立医院被要求跑到 95% 以上——那正好在曲线起飞的位置。

你的日程表。把工作日排到 100% 的人,任何一个会议超时都会推倒后面全部安排。留 20% 空白的人不是效率低,他是在买响应能力。而且这两个人的「产出」在长期看未必有差别,因为前者的时间大量花在了重新安排上。

✗ 这个直觉是错的
从 90% 涨到 95%,只多用了 5% 的产能,影响应该也就 5% 左右。 从 90% 到 95%,余量减半了(10% → 5%),所以等待翻倍还多:ρ/(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%。不过如果同时考虑到高负载下 往往也会变大(重试增多、超时增多),实际体验到的退化确实可能超过 9 倍。这个选项在实践中比它在数学上更接近真相。

这一章的一句话

等待时间反比于余量;你撞上的不是 100% 那道墙,是你的容忍线和曲线的交点。

下一章把这条曲线换个方向读:既然等待反比于余量,那么买产能的价格也随位置变化。你会看到一条漂亮得不像话的恒等式——要把等待减半,需要增加的产能恰好等于你现在的余量。在 90% 的地方,加 10% 的机器等待减半;在 99% 的地方,只要 1%。而同一句话反过来读就是噩梦。