IT 论文精读 · PAPER 74

一致性哈希与随机树(Consistent Hashing and Random Trees)

Karger, Lehman, Leighton, Levine, Lewin & Panigrahy · MIT · STOC 1997

EN →

这篇论文干了什么?

1997 年,MIT 一群做理论的人(Karger 等)为了治「网页突然爆红、服务器被挤垮」这个毛病,提出了一致性哈希——一套决定「这份东西该交给哪台机器」的规矩,好处是机器增减时几乎不用重新洗牌。第二年其中两位作者拿它创办了 Akamai;今天你刷到的视频、Amazon 的购物车、Cassandra 这类数据库,在决定「数据放哪台」时用的仍是同一个点子。

旧世界的痛:一加机器就全体搬家

要把很多东西分给几台机器,最自然的办法是按余数分:把名字换算成一个数,除以机器台数,余几就归几号机器。十台机器时人人有份、也挺均匀。

麻烦出在机器数一变。加第十一台,除数从 10 变成 11,几乎每份数据的归属都跟着变了——全集群互相搬家、网卡打满,谁也没空干正事。可你明明只想多加一台机器而已。

点子:把机器和数据摆到同一个钟面上

一致性哈希换了个摆法:想象一个钟面,每台机器按自己的名字算出一个位置钉上去,每份数据也按自己的名字算出一个位置。规矩只有一句:这份数据归「从它的位置顺时针走、碰到的第一台机器」。

为什么这样就不用全体搬家了

关键在于位置是各算各的:一份数据落在钟面哪儿只跟它自己的名字有关,跟一共有几台机器毫无关系。于是加一台机器等于往钟面上插进一个新钉子:它只从顺时针那位邻居手里接走「紧挨在自己前面那一小段」的数据,钟面其它地方一个字都不用改;掉一台机器同理,它那段顺延给下一位。所有变动都被关在一小段弧里。

还有个当年更要紧的好处:那时不同浏览器知道的缓存名单并不一样。按余数分,名单差一台答案就全变;钟面规矩下名单略有出入,绝大多数数据的落点仍然相同——大家不必先商量,就能分到同一台机器上。

一台机器要撒很多个钉子

只钉一个钉子有个副作用:钟面切出的弧有长有短,运气差的机器管一大段、运气好的只管一丁点,忙闲不均。

办法很土:让每台机器在钟面上撒几十上百个钉子(化出许多「分身」)。段数一多,长短互相抵消,各家管的总量就接近了;而且一台机器下线时,它那几十段活是被许多不同机器分头接走的,不会整个砸到某个倒霉邻居头上。

诚实一句:它摆平的是「数据份数」,不是「访问热度」——一条被全网疯抢的记录仍旧只归一台机器,照样能压垮它。

一句话记住

别按「除以机器台数取余数」分配——把机器和数据都按名字钉到同一个钟面上,数据归顺时针遇到的第一台机器。这样加减机器只波及一小段弧,搬家量从「几乎全部」降到「约等于一台机器的份」;再让每台机器多撒些钉子,忙闲就均了。

想看环的示意图、四条性质的定义和定理保证? → 切到精读版