consistent-hashing

一致性哈希:一套扛得住增减机器的分工规则

它是干嘛的。 凡是把数据按 key 摊到多台机器上存的系统——分布式缓存、分片数据库、分布式存储——都需要一条规则,只看 key 就能回答:它在哪台? 无状态的计算层永远用不上它;它只活在状态被分片的那一层。

要紧的性质不是圈。 是增减成员时的局部性:一台机器加入或离开时,只有它附近的 key 改归属,留下来的机器之间的 key 绝不互相挪窝。加一台机器,应该只搬走约 1/N 的 key,不能更多。

朴素规则恰死在这里。 用 hash(key) % N 分配:公式里含着机器数,加一台,几乎每个 key 的答案都变。值还躺在老机器上,但读的人被新公式指去了别处——对应用而言,这是一次全量缓存失效、或一次全网数据搬家,由"扩容"这个动作亲手触发。

圈是买到这条性质的一种构造。 把哈希的输出范围(假定 0..99,真实是 0..2^32)首尾接上——做成圈只是为了让最后一段绕回第一段、不留无主的尾巴,全图一条规则走到底。每台服务器把自己的身份哈希到圈上:一个标记、一个坐标。这些数字是坐标不是算子,永远不拿它们除任何东西。 key 哈希到一个点,顺时针走,碰到的第一个标记就是它的主人;每个标记身后那一段就是那台机器的辖区。写入时用这条规则决定值放哪,读取时用同一条规则找回。加一台机器就是插一个标记:它只接管前头那一段,只有那一段的 key(≈1/N)搬家。撤一台,它那一段顺手交给下一个标记。

平衡要靠虚拟节点。 每台机器只撒一个随机点,圈会被切得七歪八斜,60/25/15 的切法很常见。所以每台物理机撒 100–200 个点(名字加序号逐个哈希)。它的辖区变成许多小随机段的总和,而许多随机长度加起来必然收敛(大数定律):切分落在几个百分点之内。白捡的好处:大机器可以多撒点、按比例多扛;一台死了,它撒在各处的小段落到许多个不同邻居头上,而不是整段砸垮顺时针的下一家。

亲戚和替代品,性质相同。 Redis Cluster 把自由的圈换成 16384 个固定槽位(key 哈希进槽,槽分配给机器;扩容挪槽不挪 key)。Rendezvous hashing 连圈都不要:拿 hash(key, 每台机器名)逐个打分,最高分赢——新机器只能抢走它自己赢的 key,老归属纹丝不动。性质是魂,圈只是皮。

实操中极少自己实现。 它沉在组件里:Cassandra 的分区器就是这张环(虚拟节点叫 token),memcached 客户端内置(ketama),Envoy、HAProxy 提供它作为面向有状态后端的负载均衡模式。原生 Postgres 根本没有分片——那边的分布式答案是加一层(Citus:固定分片数 + 再平衡器,加机器时搬分片)。从业者真正要拍板的决策是选哪个组件、尤其是拿哪一列当分片键——算法是 settled 的,分片键选错才真贵。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →