← 返回题目列表

什么是一致性哈希?为什么要引入虚拟节点?

高频 中等 第 9 / 27 题 更新于 2026/10/03
一致性哈希缓存分片虚拟节点
学习 AI 实战项目

简化版

一致性哈希是一种分布式映射算法,把节点和数据 key 都映射到同一个哈希环上,key 顺时针找到的第一个节点就是它的归属节点。相比普通取模,节点扩容或下线时只会影响环上相邻一小段数据,减少缓存失效和数据迁移。虚拟节点用于让数据分布更均匀,避免少量真实节点造成倾斜。

详细版

普通取模 hash(key) % N 的问题是 N 一变,大量 key 的结果都会变化。比如缓存从 3 台扩到 4 台,绝大多数 key 都会重新映射,导致缓存雪崩式失效。

一致性哈希的做法:

  1. 把哈希空间看成一个环,比如 0 到 2^32-1。
  2. 每个服务节点通过 hash 映射到环上。
  3. 每个数据 key 也 hash 到环上。
  4. key 顺时针遇到的第一个节点负责这个 key。
  5. 新增或删除节点时,只影响该节点附近的一段 key。

虚拟节点是把一个真实节点映射成多个虚拟点,例如 nodeA#1、nodeA#2。这样节点在环上分布更均匀,节点数量少时也能减少倾斜;同时可以通过虚拟节点数量表达权重。

完整版教学

一、普通取模为什么扩容代价大

假设有 3 台缓存,key 的路由规则是 hash(key) % 3。现在扩容到 4 台,规则变成 hash(key) % 4。同一个 key 的余数大概率变化,于是原来在 A 机器的缓存可能要去 B、C、D 找。结果是大量请求打不到原缓存,全部回源数据库,数据库压力瞬间升高。

这就是普通取模最大的问题:节点数量 N 是公式的一部分,N 一变,映射整体重排。缓存、分片、长连接会话都害怕这种整体重排。

二、一致性哈希如何减少迁移

一致性哈希把哈希空间首尾相连成环。节点在环上占位置,key 也在环上占位置。key 不再对节点数取模,而是顺时针找到第一个节点。

新增节点时,新节点只会接管它逆时针方向上一段区间的 key,其他区间归属不变。删除节点时,原来归它的一段 key 顺时针迁移到下一个节点。在哈希与负载足够均匀、节点等权的理想条件下,从 N 个节点增加到 N+1 个节点,期望迁移比例约为 1/(N+1);例如 9 台扩到 10 台约迁移 10%,而普通取模通常会让大多数 key 改变落点。

这个比例是期望值,不是单次扩容保证。真实分布会受虚拟节点数量、节点权重和 key 热度影响,因此上线前还要看每个物理节点承载的 key 数、字节数和 QPS,而不能只看区间长度。

三、为什么必须有虚拟节点

如果真实节点很少,哈希环上的位置可能很不均匀。比如 A、B、C 三个节点刚好挤在一段,A 负责很小区间,C 负责巨大区间,C 就会成为热点。哈希函数再均匀,也挡不住节点样本太少造成的波动。

虚拟节点把一个真实节点拆成很多虚拟节点散布到环上。比如每台机器放 100 个虚拟点,3 台机器就有 300 个点,区间分布会平滑很多。key 命中虚拟节点后,再映射回真实机器。虚拟节点还可以做权重:性能强的机器分配更多虚拟节点,承担更多 key。

四、一致性哈希适合哪些场景

它适合“按 key 路由且希望节点变动影响小”的场景:分布式缓存、分库分表路由、对象存储分片、RPC 长连接会话粘滞、任务分片。尤其是缓存系统,减少扩容时缓存大面积失效非常重要。

但它不是万能的。如果 key 本身有热点,比如某个明星商品被疯狂访问,一致性哈希只会稳定地把热点打到同一台机器,反而可能加重热点。这时需要热点 key 拆分、多级缓存、本地缓存、请求合并等方案。

五、和哈希槽有什么关系

Redis Cluster 使用 16384 个 slot,本质上也是“先把 key 映射到固定槽,再把槽分配给节点”。这和一致性哈希目标类似:节点变化时迁移一部分槽,而不是全量 key 重新计算。区别是 slot 是离散槽位,更方便运维迁移和管理;一致性哈希是环形连续空间,更常见于客户端路由和缓存路由。

维度普通取模一致性哈希固定槽位
节点数变化大量 key 重映射主要影响相邻区间迁移被重新分配的槽
均衡方式依赖哈希与节点同质虚拟节点及权重调整节点持有槽数
路由元数据节点列表环与虚拟节点映射槽到节点映射表
运维迁移难控制单次范围以虚拟节点/区间为单位以离散槽为单位

六、成员视图、复制和故障边界

所有路由方必须对“环上有哪些节点、每个节点有哪些虚拟点”看到兼容版本。客户端 A 已加入新节点、客户端 B 仍使用旧环时,同一个 key 会被路由到不同位置;缓存场景可能只是命中率下降,存储场景则可能读写分叉。生产实现通常给成员视图加 epoch,并在变更期间做双读、转发或受控迁移。

一致性哈希只决定首选落点,不自动提供数据冗余。若复制因子为 3,可以把 key 放到顺时针方向三个不同物理节点;选择时必须跳过同一物理机的多个虚拟点,否则“3 个副本”可能仍在一台机器上。节点下线时不仅要重建主副本,还要限速补齐复制因子,避免迁移流量拖垮在线请求。

虚拟节点也不是越多越好。更多虚拟点能改善均匀性,却增加路由表、迁移任务和成员变更成本;应通过负载离散度压测选择数量,而不是照搬固定的 100 或 160。

七、常见误区与追问

环上顺序:A#1 -> C#1 -> B#1 -> A#2 -> C#2 -> B#2 -> 回到 A#1
key 落在 C#1 与 B#1 之间:首选 B#1,对应物理节点 B
新增 D#1 到该区间:只接管其逆时针前驱到 D#1 的 key

易错点:虚拟节点改善的是统计均匀性;它既不会拆散单个热点 key,也不会自动保证不同客户端拥有相同成员视图。

  • 误区:一致性哈希完全不迁移数据。 它减少迁移范围,但新增或删除节点相关区间仍要迁移。
  • 误区:不需要虚拟节点。 真实节点少时容易数据倾斜,虚拟节点能让区间更均匀。
  • 误区:一致性哈希只用于缓存。 它也可用于分片、路由、负载分配等场景。
  • 追问:为什么普通取模扩容影响大? 节点数变化会改变 key % N 的结果,大量 key 落点改变。
  • 追问:虚拟节点怎么工作? 一个真实节点对应多个环上虚拟点,分散区间,降低倾斜。
  • 追问:热点 key 怎么办? 一致性哈希解决分布,不解决热点,需要副本、拆分或本地缓存。

八、加强记忆

一致性哈希要连着四件事记:哈希环决定首选落点,节点增删只搬相邻区间,虚拟节点降低物理节点少造成的倾斜,成员版本与复制因子负责让所有路由方得到一致且有冗余的结果。它降低的是期望迁移比例,不消除热点、迁移和成员视图问题;评估时既看 key 数,也看字节数、QPS 与故障域。