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

设计分布式唯一 ID 生成器

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

EN →

这一章讲什么?

你下的每一单、发的每一条消息,系统都得给它一个编号——不能重、最好还能一眼看出谁先谁后。一台机器的时候,这事儿简单到不用想:数据库自己「从 1 开始往上加」就行。这一章讲的是:当后台变成几百台机器,这个「往上加 1」为什么会塌,以及怎么重新做一个。

打个比方

把它想成一家连锁店的取号机。只有一家店时,取号机从 1 数上去,从不出错。开到 32 家分店以后,麻烦来了:每家店都从 1 开始数,全国就会冒出 32 个「3 号」——顾客拿着号来取货,店员不知道该给谁。

三条看似顺理成章的路,都走不通

一、让所有分店都打电话回总部要号。号是不重了,可每发一个号都要打一次电话,慢;更糟的是总部一停电,全国 32 家店都发不出号。

二、每家店自己抽一串超长的随机乱码。确实撞不上,但这串码又长又看不出先后——你没法从两个编号里读出「哪单先下的」。

三、各店跳着数:1 号店数 1、33、65……,2 号店数 2、34、66……。听着挺妙,可一旦新开一家店或关掉一家,全国的数法都得重排一遍。

核心机制:把编号拆成三段拼起来

Twitter 想出的办法,是不再向任何人要号,而是用三样「本来就唯一」的东西现场拼一个:前一段写现在是几点几分几秒几毫秒,中间一段写我是哪家分店,最后一段写这一毫秒里我这家店发的第几个。

三段一拼,谁也不用问谁:不同毫秒,第一段就不一样;同一毫秒不同店,第二段不一样;同店同毫秒,第三段不一样。而且因为时间放在最前面,编号从小到大排,差不多就是从早到晚排——「有序」是白送的。这台「取号机」每家店每毫秒能发 4096 个号,够全国用 69 年。

代价是什么

这套编号的正确性,整个押在「每台机器的钟走得准」上:万一某台机器的时间被往回拨了一下,它就会把刚才那一毫秒重过一遍、把已经发过的号再发一次。

一句话记住

分布式编号的难点从来不是「别重复」——随便抽个长随机数就不会重。难的是又要不重、又要短、又要看得出先后,还不许机器之间互相打招呼。答案是把编号切成「时间 + 我是谁 + 这一刻的第几个」三段,用时间换掉了商量。

想进到具体机制、记号和示意图? → 切到精读版