一句话定义:一致性哈希(Consistent Hashing)是一种把数据分配到多台机器上的规则,它最大的好处是——增加或减少一台机器时,只需要搬动一小部分数据,而不是几乎全部重排。
先说它解决的那个痛点
假设你有 4 台缓存服务器,最简单的分法是 hash(key) % 4,把余数当作机器编号。这个办法平时工作得很好,直到你要加第 5 台机器:除数一变成 5,几乎所有 key 的余数都变了。结果是缓存几乎全量失效,请求瞬间全部压到数据库上,这就是常说的“缓存雪崩”。
环是怎么转的
一致性哈希把哈希值的取值范围想象成一个首尾相接的圆环,比如 0 到 2³²−1 绕成一圈。每台机器用自己的名字算一个哈希值,钉在环上某个位置;每个 key 也算一个哈希值,然后从它的位置顺时针往前走,遇到的第一个机器就是它的归属。
这样一来,加一台新机器时,它只是插进环上的某两个机器之间,只把原本属于顺时针下一个邻居的那一段 key 接过来,其他 key 完全不动。平均来说,只有约 1/N 的数据需要迁移,N 是机器总数。
虚拟节点:让环分得均匀
只用几台真机器钉在环上,位置很容易挤在一起,导致某台机器负责特别大的一段弧,别人闲着它忙死,这叫数据倾斜。解决办法是给每台机器在环上放很多个“虚拟节点”(virtual node),比如几百个不同名字的副本,环上就撒满了点,负载自然均匀。真机器挂了,它的虚拟节点分散出去的区间由各自的邻居接手,压力也不会全砸在一台上。
和相邻概念的区别
| 对比项 | 取模哈希 hash % N | 一致性哈希 |
|---|---|---|
| 加/减一台机器 | 约 (N−1)/N 的 key 换家 | 约 1/N 的 key 换家 |
| 扩容方式 | 往往要停机或全量重刷 | 可以在线平滑扩容 |
| 均匀性 | 依赖哈希本身 | 需要虚拟节点辅助 |
| 典型场景 | 节点数固定的简单分片 | 缓存集群、分布式存储、分片路由 |
另一类常见做法是“哈希槽”(hash slot):先把键空间切成固定数量的槽,再维护一张“槽 → 节点”的映射表,搬迁时以槽为单位。思路和一致性哈希同源——先把位置固定下来,再让一小块区域整体搬家,而不是让每个 key 重新掷骰子。
对你的实际意义
如果你在做缓存、消息队列、向量库或任何需要分片的存储,节点数大概率不会永远不变。分片策略选得好,扩容就是后台悄悄搬点数据;选得不好,就是半夜拉群、限流、回滚。以后再看到“加节点导致缓存大面积失效”“扩容要停服好几天”这类故障复盘,先去看一眼它的分片键是怎么算的。
(具体实现细节和参数以各项目官方文档为准。)
