先出一道题,你随手就能答上来,但答案会暴露这一章的全部秘密。
「做一个即时通讯,能发消息、能建群、能显示对方在不在线。」这句话,是一份合格的系统设计要求吗?
不是。因为它少了最要命的一半信息:你是谁,你在什么处境里做这件事。是三个人的创业公司,还是一家有十个团队的大厂?只有一千个用户,还是一开始就奔着一个亿去?错一次是回滚重来,还是会让几千万人同时收不到消息?这些没说清之前,「怎么设计」这个问题根本无从答起——就像你问「从这儿到那儿,走路还是开车更好」,不先告诉我多远、赶不赶时间、下不下雨,我给不了你答案。
先说清楚系统设计到底在干嘛
系统设计,说人话就是:决定一个软件由哪几块拼成、每块各管什么、数据在这些块之间怎么流、以及某一块塌了之后整个东西怎么办。它是盖房子之前那张图纸,不是砌墙那道工序。
写具体代码,是「把这面墙砌直」;系统设计,是「先定这房子几个房间、承重墙立在哪、水管电线怎么走、万一漏水从哪断闸」。前者做错了返工一面墙,后者做错了得砸了重盖。
前面第 2 章把它当流水线上的一道工序点了一下。这一章我要讲的是:为什么这道工序,恰恰是整条流水线上机器最插不进手的那一道。
系统设计的本质,是在一堆互相打架的约束里做取舍
这是全章的骨头,先立起来:系统设计没有客观最优解,因为它要同时满足一堆彼此冲突的要求,而这些要求没法一起满足。
你想让系统又快又省钱——可快往往靠多堆机器、多存几份数据,那就是花钱,快和省天生打架。你想让它既简单又灵活——可灵活意味着到处留活口、留开关,那就复杂,简单和灵活天生打架。你想让它现在好做、又将来好改——可现在图省事写死的东西,将来改起来就是拆炸弹,好做和好改天生打架。
这就像给家里买车。要能装、又要省油、又要好停、又要便宜。世上没有一辆车把这四条全占了——七座大车能装但费油难停,小车好停省油但装不下一家老小加行李。买车没有「最好的车」,只有「对你家这个处境最合适的车」。系统设计一模一样。
关键就在这:因为这些约束互相拉扯,就不存在一个放之四海皆准的正确答案。你只能在你这个具体的处境里,决定牺牲哪个、保全哪个。快和省之间那条线画在哪、简单和灵活之间那个平衡点定在哪——画在这里对你是对的,画在那里对别人是对的。这不是「有唯一解但你没找到」,是压根就没有唯一解。这跟第 5 章说的品味是一路货:都是在没有标准答案的地方拿主意,只不过品味管一段代码的好坏,系统设计管整栋楼的骨架。
同一句话,两种处境,两套完全不同的正确设计
回到开头那个即时通讯。我把它放进两个处境,你就看见「约束不同,正确答案不同」是什么样子。
处境一:三个人的创业公司
你们三个人,钱只够烧半年,用户现在两百个,最大的风险不是系统崩,是这东西根本没人要、公司先没了。
在这个处境里,正确的设计是怎么快怎么来:能用现成的就绝不自己造,所有东西先塞在一台服务器上,消息就用最笨的办法存,在线状态实现得糙一点也认。为什么?因为你最缺的是时间,最怕的是把三个月耗在打磨一个没人用的完美架构上。这里「简单、快上线」压倒一切,「将来能扛一个亿」这条约束,现在根本不该进你的考虑——你大概率活不到那天,为那天做的准备全是浪费。
处境二:大厂里的十个团队
同样一句「做个即时通讯」,你手里已经有五千万用户,一分钟发不出消息就上热搜,十个团队要在同一套系统上并行开发,谁也不能踩谁。
这个处境里,处境一那套「全塞一台服务器、怎么糙怎么来」是灾难。你必须把系统拆成一块块能各自扩容、各自出故障也不拖垮别人的部分;必须假设任何一台机器随时会挂,还要照常发消息;必须把接口定得清清楚楚,好让十个团队互不打架。这套设计又重又慢又贵——但在你这个处境里,它才是对的,因为你最怕的风险从「没人用」变成了「一挂全挂」。
看明白了吗?两套设计几乎处处相反,却各自都是对的。不是一个高级一个低级,是约束不同。把大厂那套搬给三人小队,是拿造航母的图纸去糊一条舢板,还没下水公司就烧没了;把小队那套搬给大厂,第一天上线就雪崩。脱离处境谈系统设计的好坏,是一句彻头彻尾的废话。
更狠的一层:系统设计是在赌未来
取舍已经够难了,还有更难的——你做取舍时,赌的那些东西现在都还没发生。
你赌用户会怎么涨:是慢慢爬,还是某天上了个热门突然翻一百倍?你赌需求会往哪拐:老板明年是想加视频通话,还是想international化?你赌哪儿以后会疼:是消息量爆了存不下,还是群人数多了卡成幻灯片?
这跟修路一模一样。修一条路,你得赌十年后这一带是荒地还是新城。赌它荒,修两车道,结果盖起了新城,天天堵、拆了重修,几年不得安生;赌它旺,一上来修八车道,结果一直是荒地,钱白花、路空着。修路的人不是在算一道有标准答案的题,是在赌一件还没发生的事。
系统设计就是这么在赌。而且赌错的账,是要你自己吃的——赌错了增长,要么半夜被叫起来救火,要么白花几百万堆了用不上的机器;赌错了方向,将来每加一个功能都像在结冰的地雷阵上跳舞,能疼你好几年。这就是为什么系统设计是压力最大的活:你今天签下的字,后果几年后才慢慢显形,而那时想反悔已经太贵。
为什么这件事,AI 给不了你
到这儿,AI 为什么接不了这道工序,就水落石出了。不是它算力不够、读的架构方案不够多——恰恰相反,它比谁都熟「标准答案」。问题在于系统设计这件事的性质,跟它能干的事根本不在一个平面上。三条,条条要命。
- 它没有处境和立场。它不知道你团队几个人、账上还剩多少钱、你能扛多大风险、你最怕的是「没人用」还是「一挂全挂」。而我们上面反复看到,离开处境,「好设计」这个词就没有意义。AI 手里只有全世界的平均答案,可系统设计恰恰是一件极度私人的事——它要的是「在你这个具体坑里的合理取舍」,而平均答案里没有你这个坑。
- 它不承担赌错的后果。赌未来之所以慎重,是因为赌错了有人要吃苦、要负责、要半夜爬起来救火。AI 赌错了,它没有任何损失——它不会被叫醒,不会被追责,不会用几年时间去还这笔债。一个不承担后果的东西,做不了真正的赌注决策,它只能给你列出各种可能,替你算算每种的利弊,但那一下「就赌这个,出事我扛」的拍板,它给不了,因为它根本没东西押上。
- 好设计常常要故意偏离标准答案。AI 天生往最常见、最中庸的方案走(这个毛病第 5 章拆得很细了)。可真正精彩的系统设计,常常是看穿了「你这个特殊处境不适用通行做法」,反着来一手。这种「明知道大家都那么干,但我这儿偏不」的判断,正是往上走那格新地面上的活(第 4 章说的那格),机器天生站不上去。
那 AI 到底能帮上什么
别误会成 AI 在系统设计里没用——它非常有用,只是用在刀背不是刀刃。
它能帮你把选项列全,免得你漏掉某种方案;能帮你把每个方案的账算细,这么设计大概要多少台机器、扛得住多少人;甚至你定了某一套方案,它能哗哗把那套的代码给你写出来。这些都是重活、累活,交给它又快又好。
AI 能帮你把每条路都摸清楚——多远、多堵、多花钱。但站在没有路标的岔路口,看着你这一车人、这点油、这片天色,说出「就走这条,翻车算我的」的那个人,只能是你。
系统设计这道工序值钱,不值钱在「知道有哪些做法」——那部分正在变成地板,AI 一查一大把。它值钱在最后那一下:在一堆互相打架的约束里、在一个还没发生的未来上,替你这个具体的处境拍板,并且签下自己的名字,认赌服输。列选项、算权衡、写代码,机器都能替你干;唯独那个「在没有标准答案的地方拍板并签字」的位置,空着,等你坐上去。