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

设计附近服务

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

EN →

这一章讲什么?

你在点评类 App 上按下「附近的餐厅」,一秒之内它从两亿家店里挑出你周围那几十家。这一章问:这件事到底怎么做到?答案有点反直觉——难点不在「搜」,在怎么提前给地球编好门牌号。

先说个怪事

系统其实从来不「量距离」。它不会拿你的坐标去跟两亿家店挨个算一遍谁远谁近。它早就把地球切成了一格一格、每格给了个编号,你按下按钮时它只问两句:你在哪一格?那一格里有谁?

旧世界为什么难

位置是两个数——南北一个、东西一个。数据库很擅长按一个数排队找,就像字典按拼音排好了序;却很不擅长同时按两个数找。这就像在图书馆里找「书名在 A 到 C 之间、并且厚度在 3 到 5 厘米之间」的书:两条线索各自都能筛出一大堆,可要把两堆比对到一起,就得一本本过。两亿家店这么一过,慢得没法用。

核心机制:三个直觉

① 把地球对折,折出门牌号。把世界对半分、再对半分、再对半分……每分一次就往编号后面添一个字。字越多,格子越小。妙处在于:编号开头一样,位置就一定挨得近——两个数就这样被压成了一串字,数据库又回到了它最擅长的「按一个键排队」。

② 半径不是用来算距离的,是用来挑格子大小的。你要找 500 米内的,就用小格子;找 20 公里内的,就换大格子。先用格子把候选从两亿家缩到几百家,真正的距离留到最后再算。

③ 顺手把邻居一起拿。你很可能正站在格子边上,最好吃的那家就在隔壁格里。所以系统从不只查你这一格,而是连着周围八格一起取,九格的店凑成一堆,再排序。

该怎么选

切格子有两派。一派是「全世界都切成一样大」——简单,商户开了关了改一行就行;另一派是「哪儿店多就在哪儿多切几刀」——市中心切得细、沙漠留一大格,每次取回来的数量更均匀,代价是店一变就得重算一大片。

代价还得再诚实一句:格子是方的,你要的范围是圆的——九宫格必然多捞进一些其实在半径之外的店,最后还是得挨个算一次距离筛掉。

一句话记住

「找附近」不是搜索题,是编门牌号题:把经纬度这一对二维坐标,提前压成一串一维的编号,让数据库用它最拿手的老办法(按顺序找、按开头找)去干活。剩下的功夫,都花在处理边界和「方格装圆」这两件小事上。

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