专业书籍精读 · System Design Interview 卷二 · 第 10 章

设计实时排行榜

System Design Interview Vol 2 · Ch 10 · Alex Xu & Sahn Lam · 2022

EN →

这一章讲什么?

手游里的周榜、健身 App 里的步数榜、直播间的打赏榜——它们看起来只是「把人按分数排一排」。这一章就是从头造一个这样的榜:几百万人同时在玩,分数每秒都在变,还要立刻告诉每个人「你排第几」。

先说个怪事

听起来必须动用一大堆机器,可这一章最先做的事是拿计算器算一遍。算完发现:五百万活跃玩家的月榜,数据只有几百 MB,忙的时候每秒也就两三千次改动——一台机器就装得下、也忙得过来。

这才是整章真正的教学点:先算账,再谈架构。很多「必须上分布式」的直觉,一算就散了。

旧世界为什么难

用普通数据库存一张分数表,「取前十名」很容易——按分数排个序,拿最上面十行。

难的是另一个问题:「我排第几?」数据库没有「第几」这个概念,它只能老老实实数:比我分高的人有多少个?如果你排在两千万人的中游,它就得数一千万个人,才能回你一句「第 1000 万名」。每个人都这么问一次,机器直接跪。

核心机制直觉

① 排名要能「跳着数」。把所有人按分数排成一队,只在最底下一层挨个连起来,再往上搭几层「快车道」——高层一步就跨过一大段人。关键在于:每一步都顺手记下「我这一跳跨过了几个人」。于是要算排名,只需沿着快车道跳几步,把跨过的人数加起来,而不用一个一个点名。几千万人也只要十几步。

② 一个榜就是一样东西,切不开。如果人多到一台机器放不下,直觉是拆成几台。可「排第几」问的是全场的名次——一旦把人随机分到几台机器上,每台只知道自己这几个人的顺序,谁也答不出全场第几,只能挨个问一遍再拼。

③ 所以只能按分数段来分。不是随机分人,而是按分数划段:900 分以上的放一台,800~899 的放另一台。这样「你排第几」= 比你那段高的几台机器各有多少人(一个数就够)+ 你在自己这段里排第几。代价是分数一旦挤进同一段,那台机器就被压垮。

④ 别对所有人都较真。前十名必须一分不差,但第 800 万名和第 801 万名的区别,其实没人关心。给中间的大多数人一句「你在前 12%」,比精确到个位便宜得多,而且他们更看得懂。

代价在哪

这套榜为了快,住在内存里——机器一重启就可能丢掉最近几秒到几分钟的分数,所以真账还得另外记一份在硬盘上,随时能把榜重建出来。

一句话记住

排行榜的难点从来不是「排序」,而是「我排第几」——那是个必须看全场才能回答的问题。解法是给排好的队伍加几层快车道,并在每一跳上记下跨过了多少人,于是排名能跳着数出来。真要拆成多台机器时,只能按分数段拆、不能按人随机拆,否则全场名次就散了。而对绝大多数人,一句「你在前 12%」比精确名次划算得多。

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