上一章我们把运行图(ダイヤ)摊开看,发现里面藏着一样东西叫余裕时间——大白话:故意在时刻表里多留出来的一点点缓冲,好让一个小晚点被悄悄吸收掉。这一章接着往下问一个更死磕的问题:日本铁路为什么连"晚30秒"都当回事?
先看看这份"死磕"死到什么程度。列车晚一两分钟,车站会广播道歉;晚得再多一点,铁路会当场给你开一张遅延証明書。
就是铁路开的一张书面证明,上面写着"某月某日某条线晚点了,大约几分钟"。你拿着它去公司、去学校,证明你迟到不是自己赖床,是我方的错。
一家交通公司,主动开证明承认"我错了、这锅我背",还印成标准化的单子天天发——这在很多国家听着像天方夜谭。于是很容易得出一个结论:日本人就是较真、就是礼貌过头,这是国民性。
这个结论是错的。或者说,它把结果当成了原因。准点到秒,不是一种民族性格的浪漫,而是一张高密度网络被逼出来的工程刚需。不这么干,整条线会塌。这一章就是要讲清楚这个因果。
一分钟的晚点,怎么变成一条线的瘫痪
回想第5章讲的高频:通勤高峰,发车间隔可以压到两三分钟一班。再回想信号的作用——它保证前后两辆车之间永远留着一段安全距离,一旦距离被压缩,信号会强制后车减速,甚至停下来。
现在把这两件事放一起,看一个小扰动怎么长大:
- 前面那辆车,因为某个乘客卡在车门,晚了1分钟发车。
- 它慢了,和它后面那辆车的距离就缩短了。安全间隔被吃掉,信号立刻命令后车减速。
- 后车被迫慢下来,于是它也晚了。而它一晚,又去挤它后面的第三辆……
- 就这样一辆顶一辆,晚点沿着线路一路往后传。
这是一个典型的级联故障。
级联,就是多米诺骨牌:第一张倒下,推倒第二张,第二张推倒第三张,一个小毛病顺着链条自己放大成大事故。
密度是这里的放大器。间隔越小,前车晚1分钟,后车能腾挪的余地就越少,容错窗口就越窄。低密度的线路,车与车之间空得很,一辆晚几分钟,后面根本追不上来,没人受影响;可在两分钟一班的通勤线上,同样这1分钟,足够沿线掀起一串减速。同样大小的扰动,密度越高,后果越重。
更麻烦的是它还会跨线传导。东京很多线路是互相直通的(下一章专门讲这件事——不同公司的列车直接开进对方的轨道)。一条线晚了,晚点会顺着直通的接口,漏进另一家公司的另一条线里去。网络是连成一片的,一处漏水,水会往整张网里渗。
看懂了这一层,再回头看那句广播道歉,你就明白它根本不是在讲礼貌。它是这套系统在说:我知道我这1分钟会往下游变大,我得让你们知道、也在提醒我自己——别让它继续长。准点不是为了好看,是为了不让整条线雪崩。
软件工程师会秒懂的那件事
如果你写过高并发、低延迟的系统,上面这套东西你其实早就见过,只是换了层皮。
设想一个请求量很大的服务:正常情况下每个请求几毫秒返回。突然有一个请求卡住了,慢了。会发生什么?它占着一个连接不放,它的调用方开始等、开始堆积;等超时了触发重试,重试又加大了负载;下游被压垮,又拖慢更多请求……一个慢请求,能顺着调用链把整个系统拖进重试风暴和队列雪崩。
重试风暴:系统一慢,大家都以为"是不是丢了,再发一次",于是重试的流量像滚雪球一样越堆越多,反而把本来只是有点慢的系统彻底压死。
成熟的做法是什么?盯死尾延迟,把超时设得很短。
尾延迟(tail latency):不看平均快不快,专看那最慢的一小撮请求有多慢。因为拖垮系统的从来不是"平均",是那几个掉队的。
你不会因为"平均延迟很漂亮"就放心,你会去揪那个第99百分位的慢请求,因为你知道正是它会引发级联。你设一个短超时,宁可早早失败重来,也不让一个慢请求赖在链条上把后面全拖死。
铁路的"晚30秒也在乎",是一模一样的工程直觉。30秒本身无所谓大不大,在乎的是它会不会长大。把扰动扼杀在它还小的时候,就不必在它变成瘫痪之后再去救。准点,就是铁路在卡自己的尾延迟。
准点,是整台机器的体温计
还有一层意思,准点不只是一个防级联的手段,它同时是前面所有设计的验收指标。
把前几章串起来看,这是一条依赖链:高密度的需求,逼出高频发车;高频逼出精细的运行图;运行图里必须留够余裕,折返(第5章那个终点站快速掉头)必须够快,调度必须够准。这一整套东西都做对了,最后才会长出一个结果——准点。
所以准点是这台机器的健康信号,像体温。
- 准点稳,说明每根柱子都还立着:余裕够、折返顺、信号和调度配合得上。
- 准点一旦持续掉,不用等别人报故障,你就知道下面某根柱子出问题了——可能是余裕被削太狠,可能是某个环节的处理变慢了。
一个数字,替你监控着整个系统的状态。这跟软件里盯着延迟曲线和错误率判断服务健不健康,是同一个道理:你不是喜欢那条线好看,你是靠它一眼看出机器有没有生病。
诚实的另一面:紧绷是有代价的
讲到这里,不能只吹好的。这套极致准点,是有代价的,而且代价可能很重。
第一,它把巨大的压力压在司机和调度身上。运行图精确到秒,就意味着一旦晚了,现场每个人都背着"要追回来"的心理负担。
这里必须提一件事,当作警钟。2005年,JR西日本的福知山线在尼崎发生了一起严重的脱轨事故,造成重大人员伤亡。事后普遍认为,过度追赶准点、想把晚点补回来带来的赶点压力,是诱因之一——列车在不该那么快的地方开得过快。
这件事把一条底线钉死了:准点必须让位于安全。再回头看第6章的余裕时间,你会对它有新的理解——余裕不只是用来吸收晚点、让时刻表好看的缓冲,它同时是一层安全垫。留够了余裕,司机才不必用危险的方式去抢那几十秒;把余裕削光,就等于把安全垫抽走,逼人在刀刃上追点。余裕留的从来不只是时间,是安全的呼吸空间。
第二个代价更隐蔽:一个对晚点零容忍的系统,也会把整个社会训练成零容忍。乘客习惯了列车分秒不差,于是自己的行程也就精确排到分钟,一旦晚了几分钟,反应会格外强烈。系统的紧绷,会传染给使用它的人。
所以准点这件事,是收益,也是紧绷。它是高密度网络活下去的必要条件,是防级联的闸门,是机器的体温计;但它必须始终站在安全的下面,而不是反过来。能被工程认可的准点,是"安全前提下的准点";越过那条线去抢的准点,是灾难。
下一章,我们去看那个把晚点跨公司传导的东西本身——直通运转:不同公司的列车,怎么开进彼此的轨道,又为什么明知会互相传染晚点,还是要这么干。