专业书籍精读 · System Design Interview 卷一 · 第 12 章

设计聊天系统

System Design Interview Vol 1 · Ch 12 · Alex Xu · 2020

EN →

这一章讲什么?

你在微信、WhatsApp 上跟人说话,消息「叮」一下就到了。这一章讲的就是怎么把这个「叮」造出来。它看上去比信息流简单——不就是把一句话从 A 送到 B——其实底下压着一个更基础的麻烦:在互联网最常用的那套规矩里,服务器根本没办法主动来找你。

打个比方:邮局只认「你来问」

把服务器想成一个邮局,它的规矩很死:你走进去问一句「有我的信吗」,它才会回答你。它不会主动敲你家的门。所以「寄信」毫无问题——走进去把信交给柜台就行;难的是「收信」:你怎么知道什么时候有信?

旧办法为什么难受

最笨的办法是每隔几秒跑一趟邮局问一次。你不累,邮局累:几千万人都这么问,它每秒要应付上千万次问询,而九成九的回答是「没有」。改良一点是去了就赖着不走——问完不回家,站在柜台前等,有信立刻给你,实在没有就过一阵请你先回去、你再来一趟。空跑少了,可你还是得反复来回;而且邮局也说不清你到底是回了家,还是在半路上晕倒了。

核心机制:接一根不挂断的电话线

今天的做法是第三种:你和邮局之间接一根一直不挂断的电话线。接通那一下依然是你打过去的(规矩没破),但线一旦通了,两头谁想说话都能直接说——邮局终于能主动开口了。消息之所以「叮」一下就到,就是因为这根线一直开着,不用每次重新拨号。

这根线之外,还得管三件事

一、人不在线怎么办。线断了,消息先存在服务器上,摆进一个专属于你的收件箱;你什么时候上线,什么时候来取。实在等不了就改走手机推送通知——那已经是别人家的地盘了。

二、群聊怎么发。人少的群,最省事的办法是抄 N 份:一条消息往每个人的收件箱各放一份。人少时这笔账很划算,人一多就彻底不行。

三、怎么知道谁还在。不能一断线就判「离线」——你钻进地铁网抖一下,头像就灰了,出来又亮,一路闪。所以真实系统靠心跳:在线的人每隔几秒吱一声,连着几十秒没吱声,才算真下线。

诚实的代价:这根一直开着的线不是白来的——服务器要为每个在线的人留一块内存,一台机器撑到几百万根就到顶;更麻烦的是它一旦要重启,上面所有人会在同一秒一起回头重连。

一句话记住

聊天系统真正难的不是「发」,是「收」。发消息跟你平时打开网页没区别;可要让服务器能主动找到你,就得先跟它接一根不挂断的线——之后所有复杂度:这根线接到哪台机器、断了消息存哪儿、群里怎么抄、怎么判断你还在——全是在为这一根线善后。

想进到长连接接入层、消息 ID 定序与在线状态的具体量级? → 切到精读版